diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9bb4830 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = false +trim_trailing_whitespace = true +charset = utf-8 +max_line_length = 100 +indent_style = space + +# We don't want to mess with encrypted files if they exist in the repo +[*.age] +indent_style = unset +indent_size = unset +tab_width = unset +end_of_line = unset +charset = unset +trim_trailing_whitespace = unset +insert_final_newline = unset +max_line_length = unset + +[{*.bash,.envrc}] +indent_style = tab + +[*.nix] +indent_size = 2 \ No newline at end of file diff --git a/.gitignore b/.gitignore index a35f739..daf6f01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .direnv/ *.ignore +.nixd.json \ No newline at end of file diff --git a/.nixd.nix b/.nixd.nix new file mode 100644 index 0000000..6376397 --- /dev/null +++ b/.nixd.nix @@ -0,0 +1,12 @@ +{ + formatting = { + command = "nixpkgs-fmt"; + }; + options = { + enable = true; + target = { + args = []; + installable = ".#nixosConfigurations.luna.options"; + }; + }; +} \ No newline at end of file diff --git a/flake.lock b/flake.lock index 2dd1e4f..d87ea10 100644 --- a/flake.lock +++ b/flake.lock @@ -68,6 +68,26 @@ "type": "github" } }, + "deploy-rs": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "utils": "utils" + }, + "locked": { + "lastModified": 1704875591, + "narHash": "sha256-eWRLbqRcrILgztU/m/k7CYLzETKNbv0OsT2GjkaNm8A=", + "owner": "serokell", + "repo": "deploy-rs", + "rev": "1776009f1f3fb2b5d236b84d9815f2edee463a9b", + "type": "github" + }, + "original": { + "owner": "serokell", + "repo": "deploy-rs", + "type": "github" + } + }, "disko": { "inputs": { "nixpkgs": [ @@ -75,11 +95,11 @@ ] }, "locked": { - "lastModified": 1706145859, - "narHash": "sha256-+iGHKwzKVW6aGAWfUmUSJW1KiE6WLYhKyTyWZMTw/cg=", + "lastModified": 1706491084, + "narHash": "sha256-eaEv+orTmr2arXpoE4aFZQMVPOYXCBEbLgK22kOtkhs=", "owner": "nix-community", "repo": "disko", - "rev": "5a2dc95464080764b9ca1b82b5d6d981157522be", + "rev": "f67ba6552845ea5d7f596a24d57c33a8a9dc8de9", "type": "github" }, "original": { @@ -88,6 +108,38 @@ "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": 1687265871, + "narHash": "sha256-P8AOiQk/XN8/ia4289hDHlTfWB70cRQ5pc9GRfmEdpc=", + "owner": "inclyc", + "repo": "flake-compat", + "rev": "70e56389c58bbd300d11778913b255477ebbae22", + "type": "github" + }, + "original": { + "owner": "inclyc", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { "inputs": { "systems": "systems_2" @@ -108,7 +160,7 @@ }, "flake-utils_2": { "inputs": { - "systems": "systems_3" + "systems": "systems_4" }, "locked": { "lastModified": 1705309234, @@ -147,11 +199,11 @@ }, "impermanence": { "locked": { - "lastModified": 1703656108, - "narHash": "sha256-hCSUqdFJKHHbER8Cenf5JRzjMlBjIdwdftGQsO0xoJs=", + "lastModified": 1706639736, + "narHash": "sha256-CaG4j9+UwBDfinxxvJMo6yOonSmSo0ZgnbD7aj2Put0=", "owner": "nix-community", "repo": "impermanence", - "rev": "033643a45a4a920660ef91caa391fbffb14da466", + "rev": "cd13c2917eaa68e4c49fea0ff9cada45440d7045", "type": "github" }, "original": { @@ -162,11 +214,27 @@ }, "nixpkgs": { "locked": { - "lastModified": 1705856552, - "narHash": "sha256-JXfnuEf5Yd6bhMs/uvM67/joxYKoysyE3M2k6T3eWbg=", + "lastModified": 1702272962, + "narHash": "sha256-D+zHwkwPc6oYQ4G3A1HuadopqRwUY/JkMwHz1YF7j4Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "612f97239e2cc474c13c9dafa0df378058c5ad8d", + "rev": "e97b3e4186bcadf0ef1b6be22b8558eab1cdeb5d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1706371002, + "narHash": "sha256-dwuorKimqSYgyu8Cw6ncKhyQjUDOyuXoxDTVmAXq88s=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "c002c6aa977ad22c60398daaa9be52f2203d0006", "type": "github" }, "original": { @@ -180,10 +248,12 @@ "inputs": { "agenix": "agenix", "blog": "blog", + "deploy-rs": "deploy-rs", "disko": "disko", + "flake-compat": "flake-compat_2", "flake-utils": "flake-utils_2", "impermanence": "impermanence", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs_2" } }, "systems": { @@ -230,6 +300,39 @@ "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" + } + }, + "utils": { + "inputs": { + "systems": "systems_3" + }, + "locked": { + "lastModified": 1701680307, + "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index a0e2f6f..d03e3d4 100644 --- a/flake.nix +++ b/flake.nix @@ -1,9 +1,10 @@ { - description = "Price Hiller's flake for managing system configurations"; + description = "Asgard Eternal's flake for managing system configurations"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; flake-utils.url = "github:numtide/flake-utils"; + deploy-rs.url = "github:serokell/deploy-rs"; impermanence = { url = "github:nix-community/impermanence"; }; @@ -15,6 +16,11 @@ url = "github:nix-community/disko"; inputs.nixpkgs.follows = "nixpkgs"; }; + # For the nixd language server + flake-compat = { + url = "github:inclyc/flake-compat"; + flake = false; + }; blog = { type = "gitlab"; owner = "blog"; @@ -24,25 +30,25 @@ }; }; - outputs = inputs @ { self, nixpkgs, impermanence, agenix, disko, flake-utils, blog, ... }: + + outputs = inputs @ { self, nixpkgs, deploy-rs, impermanence, agenix, disko, flake-utils, blog, ... }: let - lib = import ./lib // nixpkgs.lib; - pkgs = nixpkgs.legacyPackages."x86_64-linux"; + lib = (import ./lib { lib = nixpkgs.lib; }) // nixpkgs.lib; + persist-dir = "/persist"; defaults = { config = { - environment.etc.machine-id.source = "/nix/persist/ephemeral/etc/machine-id"; + environment.etc.machine-id.source = "${persist-dir}/ephemeral/etc/machine-id"; environment.persistence.save = { hideMounts = true; - persistentStoragePath = "/nix/persist/save"; + persistentStoragePath = "${persist-dir}/save"; }; environment.persistence.ephemeral = { - persistentStoragePath = "/nix/persist/ephemeral"; + persistentStoragePath = "${persist-dir}/ephemeral"; hideMounts = true; directories = [ "/var/lib" "/var/log" "/etc/nixos" - { directory = "/persist"; user = "root"; group = "root"; mode = "0700"; } ]; }; }; @@ -58,27 +64,41 @@ system = "x86_64-linux"; specialArgs = { inherit self; + inherit blog; inherit flake-utils; inherit inputs; inherit hostname; + inherit nixpkgs; inherit lib; - inherit blog; - secrets = "${self}/secrets/${hostname}"; - disk = "nvme0n1"; + inherit persist-dir; + root-disk = "/dev/nvme0n1"; fqdn = "orion-technologies.io"; }; modules = [ - { - _module.args = { }; - } defaults impermanence.nixosModules.impermanence agenix.nixosModules.default disko.nixosModules.disko + { config = (import "${self}/secrets" { agenix = false; inherit lib; }).${hostname}; } ./hosts/${hostname} ]; }; + deploy.nodes = { + luna = { + hostname = "luna"; + fastConnection = true; + profiles = { + system = { + sshUser = "price"; + user = "root"; + path = + deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.luna; + }; + }; + }; + }; + } // flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { @@ -90,10 +110,11 @@ devShells.default = pkgs.mkShell { - packages = with pkgs; [ age age-plugin-yubikey pkgs.agenix ]; + packages = with pkgs; [ age age-plugin-yubikey pkgs.agenix nixos-rebuild pkgs.deploy-rs ]; shellHook = '' export RULES="$PWD/secrets/secrets.nix" + nix eval --json --file ./.nixd.nix > .nixd.json ''; }; }); -} +} \ No newline at end of file diff --git a/hosts/luna/default.nix b/hosts/luna/default.nix index 857dad9..079b447 100644 --- a/hosts/luna/default.nix +++ b/hosts/luna/default.nix @@ -1,6 +1,5 @@ { config, lib, nixpkgs, ... }: { - imports = (lib.recurseFilesInDirs [ ./os ./modules ] ".nix"); system.stateVersion = "24.05"; -} +} \ No newline at end of file diff --git a/hosts/luna/modules/default.nix b/hosts/luna/modules/default.nix index 58102d0..c53be22 100644 --- a/hosts/luna/modules/default.nix +++ b/hosts/luna/modules/default.nix @@ -2,4 +2,7 @@ { time.timeZone = "America/Chicago"; -} + systemd.extraConfig = '' + DefaultTimeoutStopSec=10s + ''; +} \ No newline at end of file diff --git a/hosts/luna/modules/docker/gitlab.nix b/hosts/luna/modules/docker/gitlab.nix index 63bf340..3451782 100644 --- a/hosts/luna/modules/docker/gitlab.nix +++ b/hosts/luna/modules/docker/gitlab.nix @@ -1,4 +1,4 @@ -{ secrets, config, specialArgs, fqdn, ... }: +{ config, specialArgs, fqdn, ... }: let gitlab_home = "/var/lib/gitlab"; gitlab_host = "gitlab.${fqdn}"; @@ -42,7 +42,6 @@ in 2222 ]; - age.secrets.gitlab-runner-reg-config.file = "${secrets}/gitlab-runner-reg-config.age"; services.gitlab-runner = { enable = true; services = { diff --git a/hosts/luna/modules/services/fail2ban.nix b/hosts/luna/modules/services/fail2ban.nix index b0a2229..48ebaf4 100644 --- a/hosts/luna/modules/services/fail2ban.nix +++ b/hosts/luna/modules/services/fail2ban.nix @@ -4,4 +4,4 @@ enable = true; maxretry = 10; }; -} +} \ No newline at end of file diff --git a/hosts/luna/modules/services/gitea.nix b/hosts/luna/modules/services/gitea.nix new file mode 100644 index 0000000..ba82113 --- /dev/null +++ b/hosts/luna/modules/services/gitea.nix @@ -0,0 +1,77 @@ +{ config, fqdn, ... }: +let gitea_host = "git.${fqdn}"; +in { + age.secrets.gitea-db-pass = { + owner = config.services.gitea.user; + group = config.services.gitea.group; + }; + + services = { + postgresql = { + enable = true; + ensureDatabases = [ config.services.gitea.user ]; + ensureUsers = [{ + name = config.services.gitea.database.user; + ensureClauses = { + login = true; + createdb = true; + }; + ensureDBOwnership = true; + }]; + }; + + gitea = { + appName = "Price Hiller's Git Repositories"; + enable = true; + dump.enable = true; + database = { + type = "postgres"; + passwordFile = config.age.secrets.gitea-db-pass.path; + }; + settings = { + service.DISABLE_REGISTRATION = true; + # Extend timeouts to 1 hour + "git.timeout" = { + DEFAULT = 3600; + MIGRATE = 3600; + MIRROR = 3600; + CLONE = 3600; + PULL = 3600; + GC = 3600; + }; + markup.ENABLED = true; + mirror.DEFAULT_INTERVAL = "1h"; + server = { + DOMAIN = "${gitea_host}"; + HTTP_ADDR = "127.0.0.1"; + ROOT_URL = "https://${gitea_host}/"; + SSH_PORT = 2220; + START_SSH_SERVER = true; + DISABLE_QUERY_AUTH_TOKEN = true; + }; + session.COOKIE_SECURE = true; + "repository.upload".FILE_MAX_SIZE = 1024; + }; + }; + # gitea-actions-runner.instances = { + # + # }; + nginx.virtualHosts."${gitea_host}" = { + enableACME = true; + forceSSL = true; + locations."/".proxyPass = + "http://${config.services.gitea.settings.server.HTTP_ADDR}:${ + builtins.toString config.services.gitea.settings.server.HTTP_PORT + }"; + }; + }; + + networking.firewall.allowedTCPPorts = + [ config.services.gitea.settings.server.SSH_PORT ]; + + environment.persistence.save.directories = [{ + directory = config.services.gitea.stateDir; + user = config.services.gitea.user; + group = config.services.gitea.group; + }]; +} \ No newline at end of file diff --git a/hosts/luna/modules/services/nginx.nix b/hosts/luna/modules/services/nginx.nix index 575c928..5fe89d4 100644 --- a/hosts/luna/modules/services/nginx.nix +++ b/hosts/luna/modules/services/nginx.nix @@ -18,5 +18,4 @@ root = blog.packages.${pkgs.system}.default; locations."/".index = "home.html"; }; - -} +} \ No newline at end of file diff --git a/hosts/luna/modules/services/openssh.nix b/hosts/luna/modules/services/openssh.nix index 5849777..d816617 100644 --- a/hosts/luna/modules/services/openssh.nix +++ b/hosts/luna/modules/services/openssh.nix @@ -2,6 +2,7 @@ { services.openssh = { enable = true; + startWhenNeeded = true; # We set the hostkeys manually so they persist through reboots hostKeys = [ { @@ -19,6 +20,7 @@ settings = { PasswordAuthentication = false; PermitRootLogin = "no"; + GatewayPorts = "yes"; LogLevel = "VERBOSE"; KexAlgorithms = [ "curve25519-sha256" @@ -57,4 +59,4 @@ └────────────────────────────────────────────────────┘ ''; }; -} +} \ No newline at end of file diff --git a/hosts/luna/modules/services/postgresql.nix b/hosts/luna/modules/services/postgresql.nix new file mode 100644 index 0000000..bdbc5d8 --- /dev/null +++ b/hosts/luna/modules/services/postgresql.nix @@ -0,0 +1,33 @@ +{ config, lib, pkgs, ... }: +{ + services.postgresqlBackup = { + location = "/var/backup/postgresql"; + backupAll = true; + }; + services.postgresql = { + enable = true; + # Explicitly setting the data dir so upgrades (changing version from 15 -> 16) don't end up + # getting lost on system reboots + dataDir = "/var/lib/postgresql"; + settings = { + log_connections = true; + log_disconnections = true; + logging_collector = true; + log_statement = "all"; + log_destination = lib.mkForce "syslog,jsonlog"; + }; + ensureUsers = [ + { + name = "root"; + ensureClauses.superuser = true; + } + ]; + }; + + environment.systemPackages = [ pkgs.pgloader ]; + + environment.persistence.save.directories = [ + { directory = config.services.postgresql.dataDir; user = "postgres"; group = "postgres"; } + { directory = config.services.postgresqlBackup.location; user = "postgres"; group = "postgres"; } + ]; +} \ No newline at end of file diff --git a/hosts/luna/modules/users.nix b/hosts/luna/modules/users.nix index 083a2a0..f93a2c7 100755 --- a/hosts/luna/modules/users.nix +++ b/hosts/luna/modules/users.nix @@ -1,7 +1,5 @@ -{ pkgs, user, config, secrets, ... }: - +{ pkgs, user, config, ... }: { - age.secrets.root-pw.file = "${secrets}/root-hash-pw.age"; security.sudo.wheelNeedsPassword = false; users.users = { root.hashedPasswordFile = config.age.secrets.root-pw.path; @@ -14,4 +12,4 @@ ]; }; }; -} +} \ No newline at end of file diff --git a/hosts/luna/os/boot.nix b/hosts/luna/os/boot.nix index 950cefe..55897c7 100644 --- a/hosts/luna/os/boot.nix +++ b/hosts/luna/os/boot.nix @@ -7,8 +7,15 @@ ]; boot = { + loader = { + systemd-boot.enable = true; + efi.canTouchEfiVariables = true; + }; + kernelModules = [ "kvm-intel" ]; + kernelParams = [ "audit=1" ]; + extraModulePackages = [ ]; initrd = { - availableKernelModules = [ "xhci_pci" "ahci" "nvme" "uas" "sd_mod" ]; + availableKernelModules = [ "ahci" "xhci_pci" "virtio_pci" "sr_mod" "virtio_blk" ]; kernelModules = [ ]; systemd = { enable = true; @@ -23,17 +30,24 @@ script = '' mkdir -p /mnt DISK_LABEL="NixOS-Primary" - ATTEMPTS=5 + FOUND_DISK=0 + ATTEMPTS=50 printf "Attempting to find disk with label '%s'\n" "$DISK_LABEL" while ((ATTEMPTS > 0)); do if findfs LABEL="$DISK_LABEL"; then + FOUND_DISK=1 printf "Found disk!\n" break; fi ((ATTEMPTS--)) - sleep 3 + sleep .1 printf "Remaining disk discovery attempts: %s\n" "$ATTEMPTS" done + if (( FOUND_DISK == 0 )); then + printf "Discovery of disk with label '%s' failed! Cannot rollback!\n" "$DISK_LABEL" + exit 1 + fi + mount -t btrfs -o subvol=/ $(findfs LABEL="$DISK_LABEL") /mnt btrfs subvolume list -to /mnt/root \ | awk 'NR>2 { printf $4"\n" }' \ @@ -53,12 +67,6 @@ }; }; }; - loader = { - systemd-boot.enable = true; - efi.canTouchEfiVariables = true; - }; - kernelModules = [ "kvm-intel" ]; - extraModulePackages = [ ]; }; -} +} \ No newline at end of file diff --git a/hosts/luna/os/disk-config.nix b/hosts/luna/os/disk-config.nix deleted file mode 100644 index d61f1a8..0000000 --- a/hosts/luna/os/disk-config.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ disk ? "nvme0n1", ... }: { - disko.devices = { - disk.${disk} = { - type = "disk"; - device = "/dev/${disk}"; - content = { - type = "gpt"; - partitions = { - esp = - let - label = "NixOS-Boot"; - in - { - priority = 1; - size = "512M"; - type = "EF00"; - content = { - extraArgs = [ "-n ${label}" "-F 32" ]; - type = "filesystem"; - format = "vfat"; - mountpoint = "/boot"; - mountOptions = [ - "defaults" - ]; - }; - }; - root = - let - label = "NixOS-Primary"; - in - { - size = "100%"; - content = { - type = "btrfs"; - extraArgs = [ "-f" "--label ${label}" ]; - postCreateHook = '' - MOUNT="$(mktemp -d)" - mount "/dev/disk/by-label/${label}" "$MOUNT" -o subvol=/ - trap 'umount $MOUNT; rm -rf $MOUNT' EXIT - btrfs subvolume snapshot -r "$MOUNT/root" "$MOUNT/root-base" - ''; - subvolumes = { - "/root" = { - mountpoint = "/"; - }; - "/nix" = { - mountpoint = "/nix"; - mountOptions = [ "compress=zstd" "noatime" ]; - }; - }; - }; - }; - }; - }; - }; - }; -} diff --git a/hosts/luna/os/fs.nix b/hosts/luna/os/fs.nix new file mode 100644 index 0000000..35ce300 --- /dev/null +++ b/hosts/luna/os/fs.nix @@ -0,0 +1,87 @@ +{ modulesPath, config, lib, root-disk, persist-dir, ... }: +{ + services = { + fstrim.enable = true; + btrfs.autoScrub = { + enable = true; + fileSystems = [ + "/" + "/nix" + "/persist" + ]; + }; + snapper = { + # NOTE: According to `snapper-config(5)` the default timeline count for all timelines is 10 + # (see TIMELINE_LIMIT_HOURLY, ...DAILY, etc.) + configs.persist = { + TIMELINE_CREATE = true; + TIMELINE_CLEANUP = true; + SUBVOLUME = "${persist-dir}"; + }; + }; + }; + + fileSystems."/persist".neededForBoot = true; + + disko.devices = + { + disk.${lib.removePrefix "/dev/" root-disk} = { + type = "disk"; + device = "${root-disk}"; + content = { + type = "gpt"; + partitions = { + esp = + let + label = "NixOS-Boot"; + in + { + priority = 1; + size = "512M"; + type = "EF00"; + content = { + extraArgs = [ "-n ${label}" "-F 32" ]; + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + mountOptions = [ + "umask=0077" + "defaults" + ]; + }; + }; + root = + let + label = "NixOS-Primary"; + in + { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" "--label ${label}" ]; + postCreateHook = '' + MOUNT="$(mktemp -d)" + mount "/dev/disk/by-label/${label}" "$MOUNT" -o subvol=/ + trap 'umount $MOUNT; rm -rf $MOUNT' EXIT + btrfs subvolume snapshot -r "$MOUNT/root" "$MOUNT/root-base" + ''; + subvolumes = { + "/root" = { + mountpoint = "/"; + }; + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; + "/persist" = { + mountpoint = "/persist"; + mountOptions = [ "compress=zstd" "noatime" ]; + }; + }; + }; + }; + }; + }; + }; + }; +} \ No newline at end of file diff --git a/hosts/luna/pubkey.nix b/hosts/luna/pubkey.nix index d9a695d..c5935cf 100644 --- a/hosts/luna/pubkey.nix +++ b/hosts/luna/pubkey.nix @@ -1 +1 @@ -"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF5AtCUEvm9pSi8iI4xH5wnJ6dR9tZZY7qPS4GLJbQAW luna" \ No newline at end of file +"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJO2ufKRT1NCwp4c9cbOjxfb+/XlY8AUgnDLObA0gYaB luna" \ No newline at end of file diff --git a/install.bash b/install.bash old mode 100644 new mode 100755 index a96426e..c01fc36 --- a/install.bash +++ b/install.bash @@ -40,14 +40,15 @@ gen-system-key() { } main() { - local persist_dir="/mnt/nix/persist" + local persist_dir="/mnt/persist" local flake_install_path="${persist_dir}/ephemeral/etc/nixos" local system="${1:?"Provide system to build!"}" local flake=".#${system}" local conn="${2:?"Provide ssh connection string! (E.g. root@myhost)"}" local priv_key_path="${3:?Provide path to private key}" - shift 3 + local ssh_port="${4:-22}" + if [[ ! -r "${priv_key_path}" ]]; then printf "Unable a private key file at '%s'\n!" "${priv_key_path}" 1>&2 exit 1 @@ -67,9 +68,9 @@ main() { local new_sys_key new_sys_key="$(gen-system-key "${system}" "${priv_key_path}")" local nixos_anywhere_log - nixos_anywhere_log="$(nix run github:nix-community/nixos-anywhere -- --flake "${flake}" "${conn}" --stop-after-disko 2>&1 | tee >(cat >&2))" + nixos_anywhere_log="$(nix run github:nix-community/nixos-anywhere -- --flake "${flake}" "${conn}" --stop-after-disko 2>&1 | tee >(cat >&2) -p "${ssh_port}")" local ssh_login_key="${nixos_anywhere_log##*$'\n'}"; ssh_login_key="${ssh_login_key#*\'}"; ssh_login_key="${ssh_login_key%\'*}" - local ssh_opts="-i ${ssh_login_key} -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no" + local ssh_opts="-i ${ssh_login_key} -o GlobalKnownHostsFile=/dev/null -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p ${ssh_port} -l root" local ssh_cmd="ssh ${conn} ${ssh_opts}" local system_key_dest="${persist_dir}/ephemeral/etc/ssh/ssh_host_ed25519_key" printf "SSH Command: %s\n" "${ssh_cmd}" @@ -80,18 +81,20 @@ main() { printf "Putting new system key into place\n" printf "%s\n" "${new_sys_key}" > "${system_key_dest}" chmod 0600 "${system_key_dest}" + printf "Installing rsync for later stage\n" + nix-env -f '' -iA rsync __EOS__ printf "Copying flake to system\n"; - rsync -r "${SCRIPT_DIR}"/{*,.*} "${conn}:${flake_install_path}" -e "ssh ${ssh_opts}" --info=PROGRESS2 + local rsync_cmd="rsync -r '${SCRIPT_DIR}'/ '${conn}:${flake_install_path}' -e 'ssh ${ssh_opts}' --info=PROGRESS2" + printf "Issuing rsync command: '%s\n'" "${rsync_cmd}" + eval "${rsync_cmd}" printf "Doing final install\n" eval "${ssh_cmd}" <<- __EOS__ set -euo pipefail cd "${flake_install_path}" nix-env -f '' -iA git - sudo nixos-install --flake "git+file:${flake}" --no-root-password --no-channel-copy - reboot + sudo nixos-install --flake "git+file:${flake}" --no-root-password --no-channel-copy && reboot __EOS__ - printf "%s\n" "${ssh_cmd}" cat <<- __EOS__ ────────────────────────────────────────── @@ -103,4 +106,4 @@ main() { __EOS__ } -main "${@}" +main "${@}" \ No newline at end of file diff --git a/lib/default.nix b/lib/default.nix index d5d8de9..930c9b9 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -1,4 +1,5 @@ # Some of these functions were taken from https://github.com/NixOS/nixpkgs/blob/master/lib/ +{ lib ? (import { }).lib }: rec { hasSuffix = suffix: @@ -29,4 +30,19 @@ rec { (builtins.filter (file: hasSuffix "${suffix}" file) (recurseDir dir)); recurseFilesInDirs = dirs: suffix: (builtins.concatMap (dir: (recurseFilesInDir dir "${suffix}")) dirs); -} + # Full credit to https://stackoverflow.com/questions/54504685/nix-function-to-merge-attributes-records-recursively-and-concatenate-arrays/54505212#54505212 + recursiveMerge = attrList: + let + f = attrPath: + lib.zipAttrsWith (n: values: + if lib.tail values == [ ] + then lib.head values + else if lib.all builtins.isList values + then lib.unique (lib.concatLists values) + else if lib.all builtins.isAttrs values + then f (attrPath ++ [ n ]) values + else lib.last values + ); + in + f [ ] attrList; +} \ No newline at end of file diff --git a/secrets/default.nix b/secrets/default.nix new file mode 100644 index 0000000..54f5db5 --- /dev/null +++ b/secrets/default.nix @@ -0,0 +1,46 @@ +{ agenix ? true, lib ? import ../lib { } }: +let + masterKeys = [ + "age1yubikey1qfnj0k4mkzrn8ef5llwh2sv6hd7ckr0qml3n9hzdpz9c59ypvryhyst87k0" + ]; + hosts = { + luna = + let + secrets = "luna"; + in + { + root-pw = "${secrets}/root-hash-pw.age"; + gitlab-runner-reg-config = "${secrets}/gitlab-runner-reg-config.age"; + gitea-db-pass = "${secrets}/gitea-db-pass.age"; + }; + }; +in +if agenix then + (builtins.listToAttrs + (builtins.concatMap + (host: + let + hostSecrets = (builtins.getAttr host hosts); + in + (builtins.map + (hostSecretName: + let + secret = (builtins.getAttr hostSecretName hostSecrets); + in + { + name = builtins.toString secret; + value = { + publicKeys = [ (import ./../hosts/${host}/pubkey.nix) ] ++ masterKeys; + }; + }) + (builtins.attrNames hostSecrets))) + (builtins.attrNames hosts))) +else + (builtins.mapAttrs + (host: secrets: + (lib.recursiveMerge (builtins.map + (secretName: { + age.secrets.${secretName}.file = ./${secrets.${secretName}}; + }) + (builtins.attrNames hosts.${host})))) + hosts) \ No newline at end of file diff --git a/secrets/luna/gitea-db-pass.age b/secrets/luna/gitea-db-pass.age new file mode 100644 index 0000000..8f51e90 --- /dev/null +++ b/secrets/luna/gitea-db-pass.age @@ -0,0 +1,8 @@ +age-encryption.org/v1 +-> ssh-ed25519 1fG0ow ItVCvyKKXcmZVvuomgGsRw91c1jQCLXGPkIh2VXvGFg +NjOqD/+g+6FvOqurcaKw5LrZpmc2Tlo277ZYkv3loWU +-> piv-p256 rJs1HA AuseeP2+foV1YzNuU85cqXN/t/MxL1CSMfev9EBnn547 +ErXvkp3KKibgLNbOQmE3iM1CjgooVs/Nsup84i4U8ds +--- lWtn0ntT2K5N9LlQR69UYGyJvELufjKuEqnWceJWZdQ +{ ~et!p`8&nS W?JKYU 6?|IMQ0۸ssR,=??Oe{)^i + Agn4}(eQHU"^ؘ?}'*%,PgA Iy915Ut \ No newline at end of file diff --git a/secrets/luna/gitlab-runner-reg-config.age b/secrets/luna/gitlab-runner-reg-config.age index 22d9ce8..9e9484a 100644 --- a/secrets/luna/gitlab-runner-reg-config.age +++ b/secrets/luna/gitlab-runner-reg-config.age @@ -1,10 +1,7 @@ age-encryption.org/v1 --> ssh-ed25519 4sH96w zBi3BGIf/OJza0ADpk264QCudT5mKzxcxgfxoNI9HSw -8Ys6frvd7UeXRXPpiClCJ+qoRHiE7K+TfQhbb1o34bk --> piv-p256 rJs1HA Aw/GcBY+XMD/9++r819joYKKyIrf8gbpjgIgugLhBtBq -BTIRQ/6zl2HqJJrCGbeMwAwmp65EiU5jAs130/MoHOs --> OKjJEPyZ-grease l {KDS$m oX;O="m -29gF4VbnR6zEbojhshhTvk2tYizn32MsCDsuutl+HCmVTNPvDIkWRSMPylfsZqLY -AMl5wcis0Spit7SKkNKJVCtL/39fXu5zgJU ---- VTqUeA4weWW1vN8qr5jsTgIgbU/3rvYQX8A0gPgYGus -IVҬ*H[հ/IEz#MiҮp0M(TSyDn@[/R亱?l7 ( 7&R8 D JE5(bpn5/w/ \ No newline at end of file +-> ssh-ed25519 1fG0ow oP4nP83S4Hjf4MScoNCBbE3i4Vnzz5XiuJqaLXzRbw0 +rNOkeT8FfDLCoUnghLs8/Fpzy4qINhhIhtgB3Ep3REc +-> piv-p256 rJs1HA AiyT5IFnxwxoONmRezlvneUSYSEjglGeXYav8x7Xt+HB +JWAyCMNQNe0+LSRqdQV+f5PGixWMXFMf/wQmyoMEKNE +--- ZnfbHqBM/51+BXYGhcSzBN6k1UtZpKJshgmxrr2eFGo +?f$Ƃb t,$̐o8R;n!chzgl= 5OcBNJaH1ςu?QCfN{$MwLbs:+?ZC0 \ No newline at end of file diff --git a/secrets/luna/root-hash-pw.age b/secrets/luna/root-hash-pw.age index 9ad335b..577a78a 100644 Binary files a/secrets/luna/root-hash-pw.age and b/secrets/luna/root-hash-pw.age differ diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 0c99a5e..acebfcd 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -1,29 +1 @@ -let - root-dir = builtins.toString ./.; - lib = import ../lib; - master-keys = [ - "age1yubikey1qfnj0k4mkzrn8ef5llwh2sv6hd7ckr0qml3n9hzdpz9c59ypvryhyst87k0" - ]; - hosts = { - luna = - let - secrets = "${root-dir}/luna"; - in - [ - "${secrets}/gitlab-runner-reg-config.age" - "${secrets}/root-hash-pw.age" - ]; - }; -in -(builtins.listToAttrs - (builtins.concatMap - (host: - (builtins.map - (secret: { - name = builtins.toString secret; - value = { - publicKeys = [ (import ./../hosts/${host}/pubkey.nix) ] ++ master-keys; - }; - }) - (builtins.getAttr host hosts))) - (builtins.attrNames hosts))) +import ./default.nix { agenix = true; } \ No newline at end of file