Tangled infrastructure definitions in Nix

all: init

Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.sh>

anirudh.fi 4b27fbac

+6
common/ssh.nix
···
··· 1 + { 2 + sshKeys = [ 3 + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICf5rx2r0w98r5lOpxr+/hScABDnk1UfgTH8T2WzeNp4 icy@kvothe" 4 + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMj1Dn9YuFo2BNr993ymBa6nzyyIKAURIqMbUtfI8+4X op@mantis" 5 + ]; 6 + }
+151
flake.lock
···
··· 1 + { 2 + "nodes": { 3 + "colmena": { 4 + "inputs": { 5 + "flake-compat": "flake-compat", 6 + "flake-utils": "flake-utils", 7 + "nixpkgs": "nixpkgs", 8 + "stable": "stable" 9 + }, 10 + "locked": { 11 + "lastModified": 1684127108, 12 + "narHash": "sha256-01bfuSY4gnshhtqA1EJCw2CMsKkAx+dHS+sEpQ2+EAQ=", 13 + "owner": "zhaofengli", 14 + "repo": "colmena", 15 + "rev": "5fdd743a11e7291bd8ac1e169d62ba6156c99be4", 16 + "type": "github" 17 + }, 18 + "original": { 19 + "owner": "zhaofengli", 20 + "ref": "release-0.4.x", 21 + "repo": "colmena", 22 + "type": "github" 23 + } 24 + }, 25 + "disko": { 26 + "inputs": { 27 + "nixpkgs": [ 28 + "nixpkgs" 29 + ] 30 + }, 31 + "locked": { 32 + "lastModified": 1750040002, 33 + "narHash": "sha256-KrC9iOVYIn6ukpVlHbqSA4hYCZ6oDyJKrcLqv4c5v84=", 34 + "owner": "nix-community", 35 + "repo": "disko", 36 + "rev": "7f1857b31522062a6a00f88cbccf86b43acceed1", 37 + "type": "github" 38 + }, 39 + "original": { 40 + "owner": "nix-community", 41 + "repo": "disko", 42 + "type": "github" 43 + } 44 + }, 45 + "flake-compat": { 46 + "flake": false, 47 + "locked": { 48 + "lastModified": 1650374568, 49 + "narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=", 50 + "owner": "edolstra", 51 + "repo": "flake-compat", 52 + "rev": "b4a34015c698c7793d592d66adbab377907a2be8", 53 + "type": "github" 54 + }, 55 + "original": { 56 + "owner": "edolstra", 57 + "repo": "flake-compat", 58 + "type": "github" 59 + } 60 + }, 61 + "flake-utils": { 62 + "locked": { 63 + "lastModified": 1659877975, 64 + "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", 65 + "owner": "numtide", 66 + "repo": "flake-utils", 67 + "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", 68 + "type": "github" 69 + }, 70 + "original": { 71 + "owner": "numtide", 72 + "repo": "flake-utils", 73 + "type": "github" 74 + } 75 + }, 76 + "nixery-flake": { 77 + "flake": false, 78 + "locked": { 79 + "lastModified": 1745149613, 80 + "narHash": "sha256-rcSnsnSWA0IUjmbG2iSpvVB0702tcR3zIyU3iFJBo0g=", 81 + "owner": "tazjin", 82 + "repo": "nixery", 83 + "rev": "c6d4692b1b6eb105c9abce0411d2ef4b8708a6e1", 84 + "type": "github" 85 + }, 86 + "original": { 87 + "owner": "tazjin", 88 + "repo": "nixery", 89 + "type": "github" 90 + } 91 + }, 92 + "nixpkgs": { 93 + "locked": { 94 + "lastModified": 1746461020, 95 + "narHash": "sha256-7+pG1I9jvxNlmln4YgnlW4o+w0TZX24k688mibiFDUE=", 96 + "owner": "NixOS", 97 + "repo": "nixpkgs", 98 + "rev": "3730d8a308f94996a9ba7c7138ede69c1b9ac4ae", 99 + "type": "github" 100 + }, 101 + "original": { 102 + "owner": "NixOS", 103 + "ref": "nixos-unstable", 104 + "repo": "nixpkgs", 105 + "type": "github" 106 + } 107 + }, 108 + "nixpkgs_2": { 109 + "locked": { 110 + "lastModified": 1750134718, 111 + "narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=", 112 + "owner": "nixos", 113 + "repo": "nixpkgs", 114 + "rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c", 115 + "type": "github" 116 + }, 117 + "original": { 118 + "owner": "nixos", 119 + "ref": "nixos-unstable", 120 + "repo": "nixpkgs", 121 + "type": "github" 122 + } 123 + }, 124 + "root": { 125 + "inputs": { 126 + "colmena": "colmena", 127 + "disko": "disko", 128 + "nixery-flake": "nixery-flake", 129 + "nixpkgs": "nixpkgs_2" 130 + } 131 + }, 132 + "stable": { 133 + "locked": { 134 + "lastModified": 1688392541, 135 + "narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=", 136 + "owner": "NixOS", 137 + "repo": "nixpkgs", 138 + "rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b", 139 + "type": "github" 140 + }, 141 + "original": { 142 + "owner": "NixOS", 143 + "ref": "nixos-22.11", 144 + "repo": "nixpkgs", 145 + "type": "github" 146 + } 147 + } 148 + }, 149 + "root": "root", 150 + "version": 7 151 + }
+63
flake.nix
···
··· 1 + { 2 + description = "nix infra for tangled"; 3 + inputs = { 4 + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; 5 + colmena.url = "github:zhaofengli/colmena/release-0.4.x"; 6 + disko = { 7 + url = "github:nix-community/disko"; 8 + inputs.nixpkgs.follows = "nixpkgs"; 9 + }; 10 + nixery-flake = { 11 + type = "github"; 12 + owner = "tazjin"; 13 + repo = "nixery"; 14 + flake = false; 15 + }; 16 + }; 17 + 18 + outputs = 19 + { nixpkgs, disko, colmena, nixery-flake, ... }: 20 + { 21 + nixosConfigurations.nixery = nixpkgs.lib.nixosSystem { 22 + system = "x86_64-linux"; 23 + modules = [ 24 + disko.nixosModules.disko 25 + ./hosts/nixery/configuration.nix 26 + ]; 27 + }; 28 + colmenaHive = colmena.lib.makeHive { 29 + meta = { 30 + nixpkgs = nixpkgs.legacyPackages.x86_64-linux; 31 + specialArgs = { 32 + nixery-pkgs = import nixery-flake.outPath { 33 + pkgs = import nixpkgs { system = "x86_64-linux"; }; 34 + }; 35 + commonArgs = import ./common/ssh.nix; 36 + }; 37 + }; 38 + 39 + defaults = { pkgs, ... }: { 40 + environment.systemPackages = [ 41 + pkgs.curl 42 + ]; 43 + }; 44 + nixery = { pkgs, ... }: { 45 + deployment = { 46 + targetHost = "nixery.tangled.sh"; 47 + targetPort = 22; 48 + targetUser = "tangler"; 49 + buildOnTarget = true; 50 + }; 51 + nixpkgs.system = "x86_64-linux"; 52 + 53 + imports = [ 54 + disko.nixosModules.disko 55 + ./hosts/nixery/configuration.nix 56 + ./hosts/nixery/services/nginx.nix 57 + ./hosts/nixery/services/nixery.nix 58 + ]; 59 + time.timeZone = "Europe/Helsinki"; 60 + }; 61 + }; 62 + }; 63 + }
+61
hosts/nixery/configuration.nix
···
··· 1 + { modulesPath 2 + , lib 3 + , pkgs 4 + , ... 5 + } @ args: 6 + { 7 + imports = [ 8 + (modulesPath + "/installer/scan/not-detected.nix") 9 + (modulesPath + "/profiles/qemu-guest.nix") 10 + ./disk-config.nix 11 + ]; 12 + boot.loader.grub = { 13 + # no need to set devices, disko will add all devices that have a EF02 partition to the list already 14 + # devices = [ ]; 15 + efiSupport = true; 16 + efiInstallAsRemovable = true; 17 + }; 18 + 19 + networking.hostName = "nixery"; 20 + services = { 21 + openssh.enable = true; 22 + }; 23 + 24 + virtualisation.docker = { 25 + enable = true; 26 + logDriver = "json-file"; 27 + }; 28 + 29 + nix = { 30 + extraOptions = '' 31 + experimental-features = nix-command flakes ca-derivations 32 + warn-dirty = false 33 + keep-outputs = false 34 + ''; 35 + }; 36 + 37 + environment.systemPackages = map lib.lowPrio [ 38 + pkgs.curl 39 + pkgs.gitMinimal 40 + ]; 41 + 42 + users.users.tangler = { 43 + extraGroups = [ "networkmanager" "wheel" "docker" ]; 44 + openssh.authorizedKeys.keys = args.commonArgs.sshKeys; 45 + isNormalUser = true; 46 + }; 47 + 48 + security.sudo.extraRules = [ 49 + { 50 + users = [ "tangler" ]; 51 + commands = [ 52 + { 53 + command = "ALL"; 54 + options = [ "NOPASSWD" ]; 55 + } 56 + ]; 57 + } 58 + ]; 59 + 60 + system.stateVersion = "25.05"; 61 + }
+56
hosts/nixery/disk-config.nix
···
··· 1 + # Example to create a bios compatible gpt partition 2 + { lib, ... }: 3 + { 4 + disko.devices = { 5 + disk.disk1 = { 6 + device = lib.mkDefault "/dev/vda"; 7 + type = "disk"; 8 + content = { 9 + type = "gpt"; 10 + partitions = { 11 + boot = { 12 + name = "boot"; 13 + size = "1M"; 14 + type = "EF02"; 15 + }; 16 + esp = { 17 + name = "ESP"; 18 + size = "500M"; 19 + type = "EF00"; 20 + content = { 21 + type = "filesystem"; 22 + format = "vfat"; 23 + mountpoint = "/boot"; 24 + }; 25 + }; 26 + root = { 27 + name = "root"; 28 + size = "100%"; 29 + content = { 30 + type = "lvm_pv"; 31 + vg = "pool"; 32 + }; 33 + }; 34 + }; 35 + }; 36 + }; 37 + lvm_vg = { 38 + pool = { 39 + type = "lvm_vg"; 40 + lvs = { 41 + root = { 42 + size = "100%FREE"; 43 + content = { 44 + type = "filesystem"; 45 + format = "ext4"; 46 + mountpoint = "/"; 47 + mountOptions = [ 48 + "defaults" 49 + ]; 50 + }; 51 + }; 52 + }; 53 + }; 54 + }; 55 + }; 56 + }
+17
hosts/nixery/services/nginx.nix
···
··· 1 + { 2 + services.nginx = { 3 + enable = true; 4 + virtualHosts."nixery.tangled.sh" = { 5 + addSSL = true; 6 + enableACME = true; 7 + locations."/" = { 8 + proxyPass = "http://localhost:8080"; 9 + }; 10 + }; 11 + }; 12 + security.acme = { 13 + acceptTerms = true; 14 + defaults.email = "anirudh@tangled.sh"; 15 + }; 16 + networking.firewall.allowedTCPPorts = [ 80 443 ]; 17 + }
+39
hosts/nixery/services/nixery.nix
···
··· 1 + { nixery-pkgs, pkgs, ... }: 2 + 3 + let 4 + description = "Nixery"; 5 + storagePath = "/var/lib/nixery"; 6 + 7 + nixery = nixery-pkgs.nixery.overrideAttrs (old: { 8 + # Drop the nix-1p documentation page as it doesn't build in pure evaluation. 9 + postInstall = '' 10 + wrapProgram $out/bin/server \ 11 + --prefix PATH : ${nixery-pkgs.nixery-prepare-image}/bin \ 12 + --prefix PATH : ${pkgs.nix}/bin 13 + ''; 14 + }); 15 + 16 + in 17 + { 18 + systemd.services.nixery = { 19 + inherit description; 20 + wantedBy = [ "multi-user.target" ]; 21 + 22 + serviceConfig = { 23 + DynamicUser = true; 24 + StateDirectory = "nixery"; 25 + Restart = "always"; 26 + ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${storagePath}"; 27 + ExecStart = "${nixery}/bin/server"; 28 + }; 29 + 30 + environment = { 31 + PORT = "8080"; 32 + NIXERY_PKGS_PATH = pkgs.path; 33 + NIXERY_STORAGE_BACKEND = "filesystem"; 34 + NIX_TIMEOUT = "60"; 35 + STORAGE_PATH = storagePath; 36 + WEB_DIR = "/dev/null"; 37 + }; 38 + }; 39 + }
+6
readme.md
···
··· 1 + # infra 2 + 3 + Tangled infrastructure definitions in Nix, applied using [Colmena](https://github.com/zhaofengli/colmena). 4 + Machines are bootstrapped using [nixos-anywhere](https://github.com/nix-community/nixos-anywhere). 5 + 6 + Work in progress.