From 8ac707da3b88bc08a1693f2913fcc78ee9bced0f Mon Sep 17 00:00:00 2001 From: Adriano Caloiaro Date: Thu, 28 Nov 2024 23:33:16 -0700 Subject: [PATCH] Wip: terraform stuff done, but nixos-anywhere stil in progress --- .envrc | 1 - .gitignore | 1 + bootstrap/common/nix.nix | 33 + bootstrap/compute_providers/hetzner/main.tf | 106 ++ .../compute_providers/hetzner/variables.tf | 1 + bootstrap/compute_providers/linode/linode.tf | 41 + bootstrap/config/add_to_tailnet.tpl | 8 + bootstrap/config/nomad-server-blue.config.hcl | 71 + .../config/nomad-server-cloud-config-blue.tpl | 58 + bootstrap/disko-config.nix | 26 + bootstrap/flake.lock | 1555 +++++++++++++++++ bootstrap/flake.nix | 187 ++ bootstrap/hardware-configuration.nix | 25 + bootstrap/main.tf | 37 + bootstrap/modules/.keep | 0 bootstrap/modules/bootstrap.nix | 0 bootstrap/modules/common/qemu.nix | 7 + bootstrap/modules/nixos/default.nix | 1 + bootstrap/nixos/common/base-system.nix | 78 + bootstrap/nixos/common/incus.nix | 67 + bootstrap/nixos/common/podman.nix | 23 + .../nixos/sfos-host-01/configuration.nix | 40 + .../sfos-host-01/hardware-configuration.nix | 1 + bootstrap/overlays/default.nix | 6 + bootstrap/overlays/inputs.nix | 3 + bootstrap/todo.md | 3 + bootstrap/variables.tf | 41 + env.sample | 39 +- flake.lock | 21 + flake.nix | 7 +- 30 files changed, 2478 insertions(+), 9 deletions(-) create mode 100644 bootstrap/common/nix.nix create mode 100644 bootstrap/compute_providers/hetzner/main.tf create mode 120000 bootstrap/compute_providers/hetzner/variables.tf create mode 100644 bootstrap/compute_providers/linode/linode.tf create mode 100644 bootstrap/config/add_to_tailnet.tpl create mode 100644 bootstrap/config/nomad-server-blue.config.hcl create mode 100644 bootstrap/config/nomad-server-cloud-config-blue.tpl create mode 100644 bootstrap/disko-config.nix create mode 100644 bootstrap/flake.lock create mode 100644 bootstrap/flake.nix create mode 100644 bootstrap/hardware-configuration.nix create mode 100644 bootstrap/main.tf create mode 100644 bootstrap/modules/.keep create mode 100644 bootstrap/modules/bootstrap.nix create mode 100644 bootstrap/modules/common/qemu.nix create mode 100644 bootstrap/modules/nixos/default.nix create mode 100644 bootstrap/nixos/common/base-system.nix create mode 100644 bootstrap/nixos/common/incus.nix create mode 100644 bootstrap/nixos/common/podman.nix create mode 100644 bootstrap/nixos/sfos-host-01/configuration.nix create mode 100644 bootstrap/nixos/sfos-host-01/hardware-configuration.nix create mode 100644 bootstrap/overlays/default.nix create mode 100644 bootstrap/overlays/inputs.nix create mode 100644 bootstrap/todo.md create mode 100644 bootstrap/variables.tf diff --git a/.envrc b/.envrc index 42970c0..b44848e 100644 --- a/.envrc +++ b/.envrc @@ -13,4 +13,3 @@ if ! use flake . --impure then echo "devenv could not be built. The devenv environment was not loaded." >&2 fi - diff --git a/.gitignore b/.gitignore index a6f1b85..1fb4c0b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ **/*.devenv **/*.img **/*.direnv +**/*.terraform* .pre-commit-config.yaml diff --git a/bootstrap/common/nix.nix b/bootstrap/common/nix.nix new file mode 100644 index 0000000..5ed6f12 --- /dev/null +++ b/bootstrap/common/nix.nix @@ -0,0 +1,33 @@ +{pkgs, ...}: { + nixpkgs = { + config = { + allowUnfree = true; + }; + }; + + nix = { + package = pkgs.nix; + + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 14d"; + }; + + settings = { + trusted-users = [ + "@wheel" + ]; + + experimental-features = [ + "flakes" + "nix-command" + ]; + + trusted-public-keys = [ + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; + }; +} diff --git a/bootstrap/compute_providers/hetzner/main.tf b/bootstrap/compute_providers/hetzner/main.tf new file mode 100644 index 0000000..58e2184 --- /dev/null +++ b/bootstrap/compute_providers/hetzner/main.tf @@ -0,0 +1,106 @@ +terraform { + required_providers { + hcloud = { + source = "hetznercloud/hcloud" + version = "1.49.1" + } + + } +} + +provider "hcloud" { + token = var.compute_provider_access_token +} + +resource "hcloud_ssh_key" "admin" { + name = "sfos admin user" + public_key = var.admin_ssh_public_key +} + +##################################################################################################################### +# Instances +##################################################################################################################### + +locals { + # These are the private IP addresses that are assigned to each node + # We start at the buttom of the cidr block + 2 because 0 is not routable and 1 is reserved; hence "i + 2" below + node_private_ips = { + value = [for i in range(var.node_count) : "${cidrhost(var.internal_cidr_block, i + 2)}"] + } +} + +resource "hcloud_server" "nodes" { + count = var.node_count + name = "sfos-${count.index}" + image = "ubuntu-22.04" # This is the _initial_ OS installed on the nodes. NixOS is installed over this later + server_type = var.compute_provider_node_type + location = var.compute_provider_region + ssh_keys = [hcloud_ssh_key.admin.id] + labels = { + "sfos" : true + } + user_data = data.template_file.add_to_tailnet.rendered + firewall_ids = [hcloud_firewall.allow_ssh.id] +} + + +data "template_file" "add_to_tailnet" { + template = file("config/add_to_tailnet.tpl") + vars = { + tailscale_auth_key = var.tailscale_auth_key + admin_ssh_public_key = var.admin_ssh_public_key + } +} + +##################################################################################################################### +# Network +##################################################################################################################### + +# This network is used solely for load balancing support, since HZ load balancers need to operate on a private subnet +resource "hcloud_network" "sfos_private" { + name = "cluster-private" + ip_range = var.internal_cidr_block +} + +resource "hcloud_server_network" "sfos_network" { + count = var.node_count + server_id = hcloud_server.nodes[count.index].id + subnet_id = hcloud_network_subnet.private_subnet.id + ip = local.node_private_ips.value[count.index] +} + +resource "hcloud_network_subnet" "private_subnet" { + network_id = hcloud_network.sfos_private.id + type = "cloud" + network_zone = "us-east" + ip_range = var.internal_cidr_block +} + +resource "hcloud_firewall" "allow_ssh" { + name = "Allow SSH" + + rule { + direction = "in" + protocol = "tcp" + port = "22" + source_ips = [ + "0.0.0.0/0", + "::/0" + ] + } +} + +##################################################################################################################### +# Storage +##################################################################################################################### + +# This volume is reserved for the general purpose storage for any application +# resource "hcloud_volume" "gp-storage" { +# name = "gp-storage" +# size = 10 +# location = var.compute_provider_region +# format = "xfs" +# delete_protection = true +# } + + diff --git a/bootstrap/compute_providers/hetzner/variables.tf b/bootstrap/compute_providers/hetzner/variables.tf new file mode 120000 index 0000000..5e332d1 --- /dev/null +++ b/bootstrap/compute_providers/hetzner/variables.tf @@ -0,0 +1 @@ +/home/adriano/git/sfos/bootstrap/variables.tf \ No newline at end of file diff --git a/bootstrap/compute_providers/linode/linode.tf b/bootstrap/compute_providers/linode/linode.tf new file mode 100644 index 0000000..8184d63 --- /dev/null +++ b/bootstrap/compute_providers/linode/linode.tf @@ -0,0 +1,41 @@ +terraform { + required_providers { + linode = { + source = "linode/linode" + version = "2.31.1" + } + } +} + +provider "linode" { + token = var.compute_provider_access_token +} + +resource "linode_sshkey" "sfos_admin" { + label = "sfos-admin" + ssh_key = var.admin_ssh_public_key +} + +##################################################################################################################### +# Instances +##################################################################################################################### + +locals { + # These are the private IP addresses that are assigned to each node + # We start at the buttom of the cidr range + 2 because 0 is not routable and 1 is reserved; hence "i + 2" below + node_private_ips = { + value = [for i in range(var.instance_count) : "${cidrhost(var.internal_cidr_range, i + 2)}"] + } +} + +resource "linode_instance" "sfos_nodes" { + count = var.instance_count + name = "sfos-${count.index}" + image = "linode/alpine3.11" + label = "sfos" + group = "sfos" + tags = ["sfos"] + region = var.compute_provider_region + type = var.compute_provider_node_type + authorized_keys = [linode_sshkey.sfos_admin.id] +} diff --git a/bootstrap/config/add_to_tailnet.tpl b/bootstrap/config/add_to_tailnet.tpl new file mode 100644 index 0000000..e5465ad --- /dev/null +++ b/bootstrap/config/add_to_tailnet.tpl @@ -0,0 +1,8 @@ +#cloud-config +users: + - name: sfos + groups: users, admin + sudo: ALL=(ALL) NOPASSWD:ALL + shell: /bin/bash + ssh_authorized_keys: + - ${ admin_ssh_public_key } diff --git a/bootstrap/config/nomad-server-blue.config.hcl b/bootstrap/config/nomad-server-blue.config.hcl new file mode 100644 index 0000000..841c71b --- /dev/null +++ b/bootstrap/config/nomad-server-blue.config.hcl @@ -0,0 +1,71 @@ +leave_on_interrupt = true +leave_on_terminate = true + +server { + enabled = true + # Ideally the bootstrap expect value would reflect the number of servers set by `instance_count`, but in the interest + # of not chaning each server's "user data" every time the instance_count changes, we hard code the nomad cluster to + # bootstrap itself whenever 3 nodes are present + bootstrap_expect = 3 + + server_join { + retry_join = [ "10.0.1.2", "10.0.1.3", "10.0.1.4", "10.0.1.5", "10.0.1.6", "10.0.1.7" ] + } +} + +acl { + enabled = true +} + +client { + enabled = true + + host_volume "letsencrypt" { + path = "/var/www/certbot" + read_only = false + } + + host_volume "certbot" { + path = "/etc/certbot" + read_only = false + } + + host_network "private" { + cidr = "${ private_network_cidr }" + } + + host_network "tailnet" { + cidr = "100.64.0.0/10" + } +} + +plugin "docker" { + config { + gc { + image = true + image_delay = "3m" + container = true + + dangling_containers { + enabled = true + dry_run = false + period = "5m" + creation_grace = "5m" + } + } + + volumes { + enabled = true + selinuxlabel = "z" + } + + allow_caps = ["chown", "net_raw"] + allow_privileged = true + } +} + +plugin "raw_exec" { + config { + enabled = true + } +} diff --git a/bootstrap/config/nomad-server-cloud-config-blue.tpl b/bootstrap/config/nomad-server-cloud-config-blue.tpl new file mode 100644 index 0000000..154587c --- /dev/null +++ b/bootstrap/config/nomad-server-cloud-config-blue.tpl @@ -0,0 +1,58 @@ +#cloud-config +users: + - name: sfos + groups: users, admin + sudo: ALL=(ALL) NOPASSWD:ALL + shell: /bin/bash + ssh_authorized_keys: + - ssh-rsa ${admin_public_key} +package_update: true +package_upgrade: true +packages: + - git + - bash + - apt-transport-https + - ca-certificates + - software-properties-common + +write_files: + - encoding: b64 + content: ${ install_nomad_script } + owner: root:root + path: /root/install-nomad.sh + permissions: '0755' + - encoding: b64 + content: ${ run_nomad_script } + owner: root:root + path: /opt/nomad/bin/run-nomad.sh + permissions: '0755' + - encoding: b64 + content: ${ nomad_config_file } + path: /root/nomad.config.hcl + owner: nomad:nomad + +runcmd: + - sudo curl -fsSL https://tailscale.com/install.sh | sh + - echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf + - echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf + - sudo sysctl -p /etc/sysctl.conf + - sudo tailscale up --auth-key ${ tailscale_auth_key } --advertise-routes ${ private_network_cidr } + - sleep 2 + - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg + - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null + - sudo echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list + - wget -qO- https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo tee /etc/apt/trusted.gpg.d/pgdg.asc &>/dev/null + - sudo apt update + - apt-cache policy docker-ce + - apt install docker-ce restic rclone postgresql-client-15 -y + - usermod -G docker -a nomad + - /root/install-nomad.sh --version ${ nomad_version } --path /opt/nomad --user root + - echo '${ nomad_config_file }' | base64 -d > /opt/nomad/config/custom.hcl + - /opt/nomad/bin/run-nomad.sh --server --num-servers 10000 --config-dir /opt/nomad/config --data-dir /opt/nomad/data --bin-dir /opt/nomad/bin + - mkdir -p /etc/nginx/conf && mkdir -p /etc/certbot && mkdir -p /var/www/certbot + - echo "vm.max_map_count=262144" >> /etc/sysctl.conf + - sysctl -p + - chmod o+rw /var/run/docker.sock + - curl -L -o cni-plugins.tgz https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz + - sudo mkdir -p /opt/cni/bin + - sudo tar -C /opt/cni/bin -xzf cni-plugins.tgz diff --git a/bootstrap/disko-config.nix b/bootstrap/disko-config.nix new file mode 100644 index 0000000..e439fe1 --- /dev/null +++ b/bootstrap/disko-config.nix @@ -0,0 +1,26 @@ +{lib, ...}: { + disko.devices = { + disk.disk1 = { + device = lib.mkDefault "/dev/sda"; + content = { + type = "table"; + format = "msdos"; + partitions = [ + { + part-type = "primary"; + fs-type = "btrfs"; + name = "root"; + bootable = true; + content = { + type = "filesystem"; + format = "btrfs"; + extraArgs = ["-f" "-O block-group-tree"]; + mountpoint = "/"; + mountOptions = ["compress=zstd"]; + }; + } + ]; + }; + }; + }; +} diff --git a/bootstrap/flake.lock b/bootstrap/flake.lock new file mode 100644 index 0000000..2a79443 --- /dev/null +++ b/bootstrap/flake.lock @@ -0,0 +1,1555 @@ +{ + "nodes": { + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1723293904, + "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "owner": "ryantm", + "repo": "agenix", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "cachix": { + "inputs": { + "devenv": [ + "devenv" + ], + "flake-compat": [ + "devenv" + ], + "git-hooks": [ + "devenv" + ], + "nixpkgs": "nixpkgs" + }, + "locked": { + "lastModified": 1728672398, + "narHash": "sha256-KxuGSoVUFnQLB2ZcYODW7AVPAh9JqRlD5BrfsC/Q4qs=", + "owner": "cachix", + "repo": "cachix", + "rev": "aac51f698309fd0f381149214b7eee213c66ef0a", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "latest", + "repo": "cachix", + "type": "github" + } + }, + "cachix_2": { + "inputs": { + "devenv": "devenv_3", + "flake-compat": [ + "ess", + "devenv", + "flake-compat" + ], + "git-hooks": [ + "ess", + "devenv", + "pre-commit-hooks" + ], + "nixpkgs": [ + "ess", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728113491, + "narHash": "sha256-L1C2Mo4sZfvk6Bq2z3VARudEI00gWMg7d1SIijvR0wk=", + "owner": "cachix", + "repo": "cachix", + "rev": "b8d4825e49372937e4e377bc4eef023301497a66", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "cachix_3": { + "inputs": { + "devenv": "devenv_4", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "git-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "pre-commit-hooks" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1726520618, + "narHash": "sha256-jOsaBmJ/EtX5t/vbylCdS7pWYcKGmWOKg4QKUzKr6dA=", + "owner": "cachix", + "repo": "cachix", + "rev": "695525f9086542dfb09fde0871dbf4174abbf634", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "cachix_4": { + "inputs": { + "devenv": "devenv_5", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix", + "flake-compat": "flake-compat", + "git-hooks": "git-hooks", + "nix": "nix", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1732830318, + "narHash": "sha256-ZDtMCEfZsM8GLZichF4m+ANi+3e0ilhTuQZ0v1Sdj8Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "51abcb75d471a215c800937d4e30dc765d305c6d", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "cachix": "cachix_2", + "flake-compat": "flake-compat_3", + "nix": "nix_5", + "nixpkgs": "nixpkgs_7", + "pre-commit-hooks": "pre-commit-hooks_3" + }, + "locked": { + "lastModified": 1728573431, + "narHash": "sha256-p37PxnHGgm6dfuYpYr4iV2AV+U5F44CAK8QAP4kkSxM=", + "owner": "cachix", + "repo": "devenv", + "rev": "151a82a27c8565774452d02c63d1a35c39563919", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_3": { + "inputs": { + "cachix": "cachix_3", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_4", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "nixpkgs" + ], + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "git-hooks" + ] + }, + "locked": { + "lastModified": 1727963652, + "narHash": "sha256-os0EDjn7QVXL6RtHNb9TrZLXVm2Tc5/nZKk3KpbTzd8=", + "owner": "cachix", + "repo": "devenv", + "rev": "cb0052e25dbcc8267b3026160dc73cddaac7d5fd", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_4": { + "inputs": { + "cachix": "cachix_4", + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_3", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "nixpkgs" + ], + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "git-hooks" + ] + }, + "locked": { + "lastModified": 1723156315, + "narHash": "sha256-0JrfahRMJ37Rf1i0iOOn+8Z4CLvbcGNwa2ChOAVrp/8=", + "owner": "cachix", + "repo": "devenv", + "rev": "ff5eb4f2accbcda963af67f1a1159e3f6c7f5f91", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_5": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix_2", + "nixpkgs": "nixpkgs_4", + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "python-rewrite", + "repo": "devenv", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1732742778, + "narHash": "sha256-i+Uw8VOHzQe9YdNwKRbzvaPWLE07tYVqUDzSFTXhRgk=", + "owner": "nix-community", + "repo": "disko", + "rev": "341482e2f4d888e3f60cae1c12c3df896e7230d8", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "ess": { + "inputs": { + "devenv": "devenv_2", + "gomod2nix": "gomod2nix", + "nixpkgs": [ + "nixpkgs" + ], + "systems": "systems_4" + }, + "locked": { + "lastModified": 1729888235, + "narHash": "sha256-TD8sAXjJ4kzNwr5vL5xQCFHDc7l0AnpCsKqhUDJRbdE=", + "owner": "acaloiaro", + "repo": "ess", + "rev": "d4e0e79e427f347d6ccc373f4fb69eae47444361", + "type": "github" + }, + "original": { + "owner": "acaloiaro", + "ref": "v2.13.0", + "repo": "ess", + "type": "github" + } + }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_2": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-parts": { + "inputs": { + "nixpkgs-lib": [ + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": [ + "ess", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1727826117, + "narHash": "sha256-K5ZLCyfO/Zj9mPFldf3iwS6oZStJcU4tSpiXTMYaaL0=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "3d04084d54bedc3d6b8b736c70ef449225c361b1", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems_2" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_6": { + "inputs": { + "systems": "systems_6" + }, + "locked": { + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": [ + "devenv" + ] + }, + "locked": { + "lastModified": 1730302582, + "narHash": "sha256-W1MIJpADXQCgosJZT8qBYLRuZls2KSiKdpnTVdKBuvU=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "af8a16fe5c264f5e9e18bcee2859b40a656876cf", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "devenv", + "git-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1709087332, + "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gitignore_2": { + "inputs": { + "nixpkgs": [ + "ess", + "devenv", + "pre-commit-hooks", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "gomod2nix": { + "inputs": { + "flake-utils": "flake-utils_4", + "nixpkgs": [ + "ess", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1705314449, + "narHash": "sha256-yfQQ67dLejP0FLK76LKHbkzcQqNIrux6MFe32MMFGNQ=", + "owner": "nix-community", + "repo": "gomod2nix", + "rev": "30e3c3a9ec4ac8453282ca7f67fca9e1da12c3e6", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "gomod2nix", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "libgit2": { + "flake": false, + "locked": { + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "libgit2_2": { + "flake": false, + "locked": { + "lastModified": 1697646580, + "narHash": "sha256-oX4Z3S9WtJlwvj0uH9HlYcWv+x1hqp8mhXl7HsLu2f0=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "45fd9ed7ae1a9b74b957ef4f337bc3c8b3df01b5", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "libgit2_3": { + "flake": false, + "locked": { + "lastModified": 1728334903, + "narHash": "sha256-PhX0Rve0//Ue0WP2XLJkjmrpiMRHQNgmwffyTXx+zHk=", + "owner": "libgit2", + "repo": "libgit2", + "rev": "0da8e725f1ebacd8093aefe966e25ba71c3d995c", + "type": "github" + }, + "original": { + "owner": "libgit2", + "repo": "libgit2", + "type": "github" + } + }, + "microvm": { + "inputs": { + "flake-utils": "flake-utils_6", + "nixpkgs": [ + "nixpkgs" + ], + "spectrum": "spectrum" + }, + "locked": { + "lastModified": 1732633513, + "narHash": "sha256-6LmtOmeDpv9iHS8l0GNcppP11dKIJFMZLdFyxQ+qQBM=", + "owner": "astro", + "repo": "microvm.nix", + "rev": "093ef734d3c37669860043a87dbf1c09fc6f5b38", + "type": "github" + }, + "original": { + "owner": "astro", + "repo": "microvm.nix", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": [ + "devenv" + ], + "flake-parts": "flake-parts", + "libgit2": "libgit2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-23-11": [ + "devenv" + ], + "nixpkgs-regression": [ + "devenv" + ], + "pre-commit-hooks": [ + "devenv" + ] + }, + "locked": { + "lastModified": 1727438425, + "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", + "owner": "domenkozar", + "repo": "nix", + "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix_3": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_2" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix_4": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "flake-compat" + ], + "flake-parts": "flake-parts_2", + "libgit2": "libgit2_2", + "nixpkgs": "nixpkgs_5", + "nixpkgs-23-11": "nixpkgs-23-11", + "nixpkgs-regression": "nixpkgs-regression_3", + "pre-commit-hooks": "pre-commit-hooks" + }, + "locked": { + "lastModified": 1727438425, + "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", + "owner": "domenkozar", + "repo": "nix", + "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nix_5": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "flake-compat" + ], + "flake-parts": "flake-parts_3", + "libgit2": "libgit2_3", + "nixpkgs": "nixpkgs_6", + "nixpkgs-23-11": "nixpkgs-23-11_2", + "nixpkgs-regression": "nixpkgs-regression_4", + "pre-commit-hooks": "pre-commit-hooks_2" + }, + "locked": { + "lastModified": 1727438425, + "narHash": "sha256-X8ES7I1cfNhR9oKp06F6ir4Np70WGZU5sfCOuNBEwMg=", + "owner": "domenkozar", + "repo": "nix", + "rev": "f6c5ae4c1b2e411e6b1e6a8181cc84363d6a7546", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.24", + "repo": "nix", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1732483221, + "narHash": "sha256-kF6rDeCshoCgmQz+7uiuPdREVFuzhIorGOoPXMalL2U=", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "45348ad6fb8ac0e8415f6e5e96efe47dd7f39405", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "master", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1730531603, + "narHash": "sha256-Dqg6si5CqIzm87sp57j5nTaeBbWhHFaVyG7V6L8k3lY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "7ffd9ae656aec493492b44d0ddfb28e79a1ea25d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-23-11": { + "locked": { + "lastModified": 1717159533, + "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + } + }, + "nixpkgs-23-11_2": { + "locked": { + "lastModified": 1717159533, + "narHash": "sha256-oamiKNfr2MS6yH64rUn99mIZjc45nGJlj9eGth/3Xuw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a62e6edd6d5e1fa0329b8653c801147986f8d446", + "type": "github" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_2": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_3": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_4": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1678872516, + "narHash": "sha256-/E1YwtMtFAu2KUQKV/1+KFuReYPANM2Rzehk84VxVoc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9b8e5abb18324c7fe9f07cb100c3cd4a29cda8b8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-22.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1716977621, + "narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "4267e705586473d3e5c8d50299e71503f16a6fb6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_4": { + "locked": { + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_5": { + "locked": { + "lastModified": 1717432640, + "narHash": "sha256-+f9c4/ZX5MWDOuB1rKoWj+lBNm0z0rs4CK47HBLxy1o=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "88269ab3044128b7c2f4c7d68448b2fb50456870", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_6": { + "locked": { + "lastModified": 1728573531, + "narHash": "sha256-WYerSn61NRVGaWlJaprHWDU9rGgMJVXlYZ+kmHB/gC8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1dfc201544fed6086383b4477d8d5c30055215c7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "release-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_7": { + "locked": { + "lastModified": 1716977621, + "narHash": "sha256-Q1UQzYcMJH4RscmpTkjlgqQDX5yi1tZL0O345Ri6vXQ=", + "owner": "cachix", + "repo": "devenv-nixpkgs", + "rev": "4267e705586473d3e5c8d50299e71503f16a6fb6", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "rolling", + "repo": "devenv-nixpkgs", + "type": "github" + } + }, + "nixpkgs_8": { + "locked": { + "lastModified": 1732521221, + "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "pre-commit-hooks": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix" + ], + "flake-utils": "flake-utils_2", + "gitignore": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix" + ], + "nixpkgs": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "ess", + "devenv", + "cachix", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712897695, + "narHash": "sha256-nMirxrGteNAl9sWiOhoN5tIHyjBbVi5e2tgZUgZlK3Y=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "40e6053ecb65fcbf12863338a6dcefb3f55f1bf8", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_2": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "nix" + ], + "gitignore": [ + "ess", + "devenv", + "nix" + ], + "nixpkgs": [ + "ess", + "devenv", + "nix", + "nixpkgs" + ], + "nixpkgs-stable": [ + "ess", + "devenv", + "nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1728580416, + "narHash": "sha256-nKttjKg6lE7O5S+wlBOkXsUGdOgVxZ8SWaCOyodW5so=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "4ebefcac44b5116cf5741be858245db769ddedd1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "pre-commit-hooks_3": { + "inputs": { + "flake-compat": [ + "ess", + "devenv", + "flake-compat" + ], + "flake-utils": "flake-utils_3", + "gitignore": "gitignore_2", + "nixpkgs": [ + "ess", + "devenv", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1686050334, + "narHash": "sha256-R0mczWjDzBpIvM3XXhO908X5e2CQqjyh/gFbwZk/7/Q=", + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "rev": "6881eb2ae5d8a3516e34714e7a90d9d95914c4dc", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "pre-commit-hooks.nix", + "type": "github" + } + }, + "root": { + "inputs": { + "agenix": "agenix", + "devenv": "devenv", + "disko": "disko", + "ess": "ess", + "flake-utils": "flake-utils_5", + "microvm": "microvm", + "nixos-hardware": "nixos-hardware", + "nixpkgs": "nixpkgs_8", + "stable": "stable", + "systems": "systems_7" + } + }, + "spectrum": { + "flake": false, + "locked": { + "lastModified": 1729945407, + "narHash": "sha256-iGNMamNOAnVTETnIVqDWd6fl74J8fLEi1ejdZiNjEtY=", + "ref": "refs/heads/main", + "rev": "f1d94ee7029af18637dbd5fdf4749621533693fa", + "revCount": 764, + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + }, + "original": { + "type": "git", + "url": "https://spectrum-os.org/git/spectrum" + } + }, + "stable": { + "locked": { + "lastModified": 1732749044, + "narHash": "sha256-T38FQOg0BV5M8FN1712fovzNakSOENEYs+CSkg31C9Y=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "0c5b4ecbed5b155b705336aa96d878e55acd8685", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_2": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_3": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_7": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/bootstrap/flake.nix b/bootstrap/flake.nix new file mode 100644 index 0000000..9be3bf4 --- /dev/null +++ b/bootstrap/flake.nix @@ -0,0 +1,187 @@ +{ + description = "sfos (self-host os)"; + nixConfig = { + extra-substituters = ["https://microvm.cachix.org"]; + extra-trusted-public-keys = ["microvm.cachix.org-1:oXnBc6hRE3eX5rSYdRyMYXnfzcCxC7yKPTbZXALsqys="]; + }; + + inputs = { + flake-utils.url = "github:numtide/flake-utils"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + stable.url = "github:NixOS/nixpkgs/nixos-24.05"; + systems.url = "github:nix-systems/default"; + nixos-hardware.url = "github:NixOS/nixos-hardware/master"; + devenv.url = "github:cachix/devenv"; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + ess = { + url = "github:acaloiaro/ess/v2.13.0"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + microvm = { + url = "github:astro/microvm.nix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + agenix = { + url = "github:ryantm/agenix"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = inputs @ { + agenix, + devenv, + disko, + microvm, + nixpkgs, + self, + stable, + systems, + ... + }: let + inherit (self) outputs; + lib = nixpkgs.lib; + pkgs = nixpkgs.legacyPackages."x86_64-linux"; + system = "x86_64-linux"; + forEachSystem = nixpkgs.lib.genAttrs (import systems); + in { + inherit lib; + packages.${system} = { + default = self.packages.${system}.my-microvm; + my-microvm = self.nixosConfigurations.my-microvm.config.microvm.declaredRunner; + }; + devShells = forEachSystem (system: let + config = self.devShells.${system}.default.config; + in { + default = devenv.lib.mkShell { + inherit inputs pkgs; + modules = [ + { + languages = { + nix.enable = true; + }; + + packages = with pkgs; [ + opentofu + pre-commit + nixos-anywhere + ]; + + enterShell = + #bash + '' + run-show-help + ''; + + pre-commit.hooks.env-sample-sync = { + enable = true; + always_run = true; + pass_filenames = false; + name = "env-sample-sync"; + description = "Sync secrets to env.sample"; + entry = "${inputs.ess.packages.${system}.default}/bin/ess"; + }; + + scripts = { + run-show-help = { + description = "Show this help text"; + exec = '' + echo + echo Helper scripts available: + echo + ${pkgs.gnused}/bin/sed -e 's| |XX|g' \ + -e 's|=| |' <.useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.enp1s0.useDHCP = lib.mkDefault true; + # networking.interfaces.enp7s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/bootstrap/main.tf b/bootstrap/main.tf new file mode 100644 index 0000000..6f3327d --- /dev/null +++ b/bootstrap/main.tf @@ -0,0 +1,37 @@ +terraform { + backend "s3" { + bucket = "mycorp" + key = "sfos/sfos-cluster.tfstate" + region = "us-east-1" + endpoints = { + s3 = "https://us-east-1.linodeobjects.com" + } + skip_credentials_validation = true + skip_requesting_account_id = true + skip_s3_checksum = true + skip_region_validation = true + skip_metadata_api_check = true + } + + required_providers { + tailscale = { + source = "tailscale/tailscale" + version = "0.17.2" + } + } +} + +provider "tailscale" { + api_key = "my_api_key" + tailnet = "example.com" +} + +module "compute_provider" { + source = "./compute_providers/hetzner" + compute_provider_access_token = var.compute_provider_access_token + compute_provider_node_type = var.compute_provider_node_type + compute_provider_region = var.compute_provider_region + admin_ssh_public_key = var.admin_ssh_public_key + tailscale_auth_key = var.tailscale_auth_key +} + diff --git a/bootstrap/modules/.keep b/bootstrap/modules/.keep new file mode 100644 index 0000000..e69de29 diff --git a/bootstrap/modules/bootstrap.nix b/bootstrap/modules/bootstrap.nix new file mode 100644 index 0000000..e69de29 diff --git a/bootstrap/modules/common/qemu.nix b/bootstrap/modules/common/qemu.nix new file mode 100644 index 0000000..c15a02b --- /dev/null +++ b/bootstrap/modules/common/qemu.nix @@ -0,0 +1,7 @@ +{...}: { + boot.kernelParams = [ + "console=tty1" + "console=ttyS0,115200" + ]; + services.qemuGuest.enable = true; +} diff --git a/bootstrap/modules/nixos/default.nix b/bootstrap/modules/nixos/default.nix new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/bootstrap/modules/nixos/default.nix @@ -0,0 +1 @@ +{} diff --git a/bootstrap/nixos/common/base-system.nix b/bootstrap/nixos/common/base-system.nix new file mode 100644 index 0000000..b3c632f --- /dev/null +++ b/bootstrap/nixos/common/base-system.nix @@ -0,0 +1,78 @@ +{ + lib, + pkgs, + self, + ... +}: { + imports = [ + ../../common/nix.nix + ]; + + boot = { + initrd.systemd.enable = true; + tmp = { + cleanOnBoot = true; + useTmpfs = true; + }; + + loader = { + efi.canTouchEfiVariables = true; + systemd-boot = { + enable = true; + configurationLimit = 20; + }; + }; + }; + + environment = { + systemPackages = with pkgs; [ + lsof + wget + ]; + }; + + i18n = let + locale = "en_US.UTF-8"; + in { + defaultLocale = locale; + extraLocaleSettings = { + LC_ADDRESS = locale; + LC_IDENTIFICATION = locale; + LC_MEASUREMENT = locale; + LC_MONETARY = locale; + LC_NAME = locale; + LC_NUMERIC = locale; + LC_PAPER = locale; + LC_TELEPHONE = locale; + LC_TIME = locale; + }; + }; + + networking = { + enableIPv6 = false; + }; + + programs = {}; + + services = { + fstrim.enable = true; + locate.enable = true; + rsyslogd.enable = true; + openssh = { + enable = true; + settings.PermitRootLogin = "no"; + }; + }; + + security = { + rtkit.enable = true; + }; + + systemd.services.nix-daemon = { + environment.TMPDIR = "/var/tmp"; + }; + + time.timeZone = "America/New_York"; + users.mutableUsers = false; + system.configurationRevision = lib.mkIf (self ? rev) self.rev; +} diff --git a/bootstrap/nixos/common/incus.nix b/bootstrap/nixos/common/incus.nix new file mode 100644 index 0000000..4f020c8 --- /dev/null +++ b/bootstrap/nixos/common/incus.nix @@ -0,0 +1,67 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.sfos.incus; +in { + options.sfos.incus.enable = mkEnableOption "enable incus"; + options.sfos.incus.admin-users = mkOption { + type = with types; listOf str; + description = "A list of system users who are incus admins"; + default = []; + }; + + config = mkIf cfg.enable { + virtualisation = { + incus = { + enable = true; + + # Setup the incus cluster + preseed = { + networks = [ + { + config = { + "ipv4.address" = "10.0.100.1/24"; + "ipv4.nat" = "true"; + }; + name = "incusbr0"; + type = "bridge"; + } + ]; + profiles = [ + { + devices = { + eth0 = { + name = "eth0"; + network = "incusbr0"; + type = "nic"; + }; + root = { + path = "/"; + pool = "default"; + size = "10GiB"; + type = "disk"; + }; + }; + name = "default"; + } + ]; + storage_pools = [ + { + config = { + source = "/var/lib/incus/storage-pools/default"; + }; + driver = "dir"; + name = "default"; + } + ]; + }; + }; + }; + + # Add users as incus admins + users.groups."incus-admin" = mkIf (cfg.admin-users != []) {members = cfg.admin-users;}; + }; +} diff --git a/bootstrap/nixos/common/podman.nix b/bootstrap/nixos/common/podman.nix new file mode 100644 index 0000000..4af85ef --- /dev/null +++ b/bootstrap/nixos/common/podman.nix @@ -0,0 +1,23 @@ +{pkgs, ...}: { + virtualisation = { + podman = { + enable = true; + # Alias all docker commands to podman + dockerCompat = true; + # Required for containers under podman-compose to be able to talk to each other. + defaultNetwork.settings.dns_enabled = true; + autoPrune = { + enable = true; + dates = "weekly"; + flags = [ + "--filter=until=24h" + # Don't prune containers flagged 'important' + "--filter=label!=important" + ]; + }; + }; + }; + environment.systemPackages = with pkgs; [ + podman-compose + ]; +} diff --git a/bootstrap/nixos/sfos-host-01/configuration.nix b/bootstrap/nixos/sfos-host-01/configuration.nix new file mode 100644 index 0000000..f4de161 --- /dev/null +++ b/bootstrap/nixos/sfos-host-01/configuration.nix @@ -0,0 +1,40 @@ +{config, ...}: { + imports = [ + ../common/base-system.nix + ../common/podman.nix + ../common/incus.nix + ./hardware-configuration.nix + ../../modules/common/qemu.nix + ]; + + users.users.sfos = { + isNormalUser = true; + extraGroups = ["wheel"]; + initialPassword = "Test.123"; + }; + + networking = { + hostName = "sfos-host-01"; + nftables.enable = true; + firewall = { + allowedTCPPorts = [22]; + allowedUDPPorts = [config.services.tailscale.port]; + interfaces.incusbr0.allowedTCPPorts = [ + 22 + 53 + 67 + ]; + interfaces.incusbr0.allowedUDPPorts = [ + 53 + 67 + ]; + }; + }; + + sfos.incus = { + enable = true; + admin-users = ["sfos"]; + }; + services.tailscale.enable = true; + system.stateVersion = "24.05"; +} diff --git a/bootstrap/nixos/sfos-host-01/hardware-configuration.nix b/bootstrap/nixos/sfos-host-01/hardware-configuration.nix new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/bootstrap/nixos/sfos-host-01/hardware-configuration.nix @@ -0,0 +1 @@ +{} diff --git a/bootstrap/overlays/default.nix b/bootstrap/overlays/default.nix new file mode 100644 index 0000000..2b8d5e1 --- /dev/null +++ b/bootstrap/overlays/default.nix @@ -0,0 +1,6 @@ +# This file defines overlays +{inputs, ...}: { + nixpkgs.overlays = [ + #(import ./inputs.nix {inherit inputs;}) + ]; +} diff --git a/bootstrap/overlays/inputs.nix b/bootstrap/overlays/inputs.nix new file mode 100644 index 0000000..6f1bf4a --- /dev/null +++ b/bootstrap/overlays/inputs.nix @@ -0,0 +1,3 @@ +{inputs, ...}: final: prev: { + # exmple = inputs.example.packages.${final.system}.default; +} diff --git a/bootstrap/todo.md b/bootstrap/todo.md new file mode 100644 index 0000000..e1fb8df --- /dev/null +++ b/bootstrap/todo.md @@ -0,0 +1,3 @@ +- Secrets https://github.com/nix-community/nixos-anywhere/blob/main/docs/howtos/secrets.md +- Fix partitioning +- Get output from tofu to connect and install using nixos-anywhere diff --git a/bootstrap/variables.tf b/bootstrap/variables.tf new file mode 100644 index 0000000..e93d8f6 --- /dev/null +++ b/bootstrap/variables.tf @@ -0,0 +1,41 @@ +variable "tailscale_auth_key" { + type = string + description = "Tailscale key for nodes joining the Tailnet" +} + +variable "admin_ssh_public_key" { + type = string + description = "The SSH Public key that can access nodes via SSH after provisioning" +} + +variable "node_count" { + type = number + default = 1 + description = "the number of nodes to create" +} + +variable "internal_cidr_block" { + default = "10.0.1.0/24" + description = "the cidr block for the cluster's internal subnet" +} + +variable "compute_provider_access_token" { + type = string + description = "Access token for accessing your compute provider's provisioning API" + sensitive = true +} + +variable "compute_provider_node_type" { + type = string + description = "The name your compute provider uses to refer to the type of compute resource you'll be creating, e.g Hetzner 'cpx21' for CPX21 server" + sensitive = true +} + +variable "compute_provider_region" { + description = "Your compute provider's name for the region in which to provision nodes" +} + + + + + diff --git a/env.sample b/env.sample index eb5c2b0..ac32d87 100644 --- a/env.sample +++ b/env.sample @@ -1,12 +1,37 @@ -# These credentials are Linode credentials for storing terraform state in a Linode bucket +# sfos uses opentofu/terraform to provision infrastrucutre. By default, infrastructure state may be stored in any s3-compatible object store. +# Despite the name of this variables, this access key need not be for AWS (Amazon Web Services) +# +# AWS_ACCESS_KEY_ID is the access key for reading/writing opentofu/terraform state to/from a s3-compatible object store AWS_ACCESS_KEY_ID= + +# sfos uses opentofu/terraform to provision infrastrucutre. By default, infrastructure state may be stored in any s3-compatible object store +# Despite the name of this variables, this access key need not be for AWS (Amazon Web Services) +# +# AWS_SECRET_ACCESS_KEY is the secret access key for reading/writing opentofu/terraform to/from a s3-compatible object store AWS_SECRET_ACCESS_KEY= -# Hetzner DNS API token -TF_VAR_hetzner_dns_access_token= - -# Hetnzer Compute API token -TF_VAR_hetzner_compute_access_token= - # Tailscale key to join the Tailnet TF_VAR_tailscale_auth_key= + +# Access token for accessing your compute provider's provisioning API +export TF_VAR_compute_provider_access_token= + +# The SSH public key of the admin user who is able to SSH into created nodes +export TF_VAR_admin_ssh_public_key= + +####################################################################################################################### +# Compute provider configuration +####################################################################################################################### + +# The name your compute provider uses to refer to the type of compute resource/node you're creating, e.g Hetzner 'cpx21' for CPX21 server +export TF_VAR_compute_provider_node_type= + +# The region in which to create compute nodes +export TF_VAR_compute_provider_region= + +# The CIDR block for the cluster's private subnet +# export TF_VAR_internal_cidr_block="10.0.1.0/24" + +####################################################################################################################### +# Compute provider configuration +####################################################################################################################### diff --git a/flake.lock b/flake.lock index 186cbff..153430f 100644 --- a/flake.lock +++ b/flake.lock @@ -355,6 +355,26 @@ "type": "github" } }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1732742778, + "narHash": "sha256-i+Uw8VOHzQe9YdNwKRbzvaPWLE07tYVqUDzSFTXhRgk=", + "owner": "nix-community", + "repo": "disko", + "rev": "341482e2f4d888e3f60cae1c12c3df896e7230d8", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, "ess": { "inputs": { "devenv": "devenv_2", @@ -1382,6 +1402,7 @@ "inputs": { "agenix": "agenix", "devenv": "devenv", + "disko": "disko", "ess": "ess", "flake-utils": "flake-utils_5", "microvm": "microvm", diff --git a/flake.nix b/flake.nix index 0c02d08..aef4a0f 100644 --- a/flake.nix +++ b/flake.nix @@ -12,7 +12,10 @@ systems.url = "github:nix-systems/default"; nixos-hardware.url = "github:NixOS/nixos-hardware/master"; devenv.url = "github:cachix/devenv"; - + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; ess = { url = "github:acaloiaro/ess/v2.13.0"; inputs.nixpkgs.follows = "nixpkgs"; @@ -61,7 +64,9 @@ }; packages = with pkgs; [ + opentofu pre-commit + nixos-anywhere ]; enterShell =