diff --git a/common/admins.nix b/common/admins.nix index 84f9231..8c40fd8 100644 --- a/common/admins.nix +++ b/common/admins.nix @@ -1,16 +1,17 @@ let keys = import ./ssh-keys.nix; -in { - users.users.root.openssh.authorizedKeys.keys = - keys.users.delroth ++ - keys.users.emilylange ++ - keys.users.hexchen ++ - keys.users.jade ++ - keys.users.janik ++ - keys.users.k900 ++ - keys.users.lukegb ++ - keys.users.maxine ++ - keys.users.raito ++ - keys.users.thubrecht ++ - keys.users.yuka; +in +{ + users.users.root.openssh.authorizedKeys.keys = + keys.users.delroth + ++ keys.users.emilylange + ++ keys.users.hexchen + ++ keys.users.jade + ++ keys.users.janik + ++ keys.users.k900 + ++ keys.users.lukegb + ++ keys.users.maxine + ++ keys.users.raito + ++ keys.users.thubrecht + ++ keys.users.yuka; } diff --git a/common/base-server.nix b/common/base-server.nix index c3f0251..e208a8c 100644 --- a/common/base-server.nix +++ b/common/base-server.nix @@ -1,7 +1,6 @@ -{ lib, pkgs, ... }: { - imports = [ - ./known-ssh-keys.nix - ]; +{ lib, pkgs, ... }: +{ + imports = [ ./known-ssh-keys.nix ]; nixpkgs.overlays = import ../overlays; @@ -36,7 +35,8 @@ services.journald.extraConfig = "SystemMaxUse=512M"; boot.kernelParams = [ - "panic=30" "boot.panic_on_fail" + "panic=30" + "boot.panic_on_fail" ]; boot.kernel.sysctl = { diff --git a/common/hardening.nix b/common/hardening.nix index e3b6df2..9bcd99e 100644 --- a/common/hardening.nix +++ b/common/hardening.nix @@ -3,9 +3,9 @@ { nix.settings.allowed-users = [ "root" ]; - boot.specialFileSystems = lib.mkIf (!config.security.rtkit.enable && !config.security.polkit.enable) { - "/proc".options = [ "hidepid=2" ]; - }; + boot.specialFileSystems = lib.mkIf ( + !config.security.rtkit.enable && !config.security.polkit.enable + ) { "/proc".options = [ "hidepid=2" ]; }; boot.kernel.sysctl."kernel.dmesg_restrict" = 1; @@ -14,9 +14,7 @@ settings.KbdInteractiveAuthentication = false; # prevents mutable /home/$user/.ssh/authorized_keys from being loaded to ensure that all user keys are config managed - authorizedKeysFiles = lib.mkForce [ - "/etc/ssh/authorized_keys.d/%u" - ]; + authorizedKeysFiles = lib.mkForce [ "/etc/ssh/authorized_keys.d/%u" ]; }; users.mutableUsers = false; diff --git a/common/raito-proxy-aware-nginx.nix b/common/raito-proxy-aware-nginx.nix index 59fb332..3f68a64 100644 --- a/common/raito-proxy-aware-nginx.nix +++ b/common/raito-proxy-aware-nginx.nix @@ -5,31 +5,52 @@ let cfg = config.bagel.raito.v6-proxy-awareness; allowedUpstream = "2001:bc8:38ee:99::1/128"; in - { - options.bagel.raito.v6-proxy-awareness.enable = mkEnableOption "the kurisu.lahfa.xyz's sniproxy awareness for NGINX"; - config = mkIf cfg.enable { - services.nginx = { - # IPv6-only server - defaultListen = [ - { addr = "[::0]"; proxyProtocol = true; port = 444; ssl = true; } - { addr = "[::0]"; port = 443; ssl = true; } - { addr = "[::0]"; port = 80; ssl = false; } - # Private networking - { addr = "127.0.0.1"; port = 80; ssl = false; } - { addr = "[::1]"; port = 80; ssl = false; } - ]; +{ + options.bagel.raito.v6-proxy-awareness.enable = mkEnableOption "the kurisu.lahfa.xyz's sniproxy awareness for NGINX"; + config = mkIf cfg.enable { + services.nginx = { + # IPv6-only server + defaultListen = [ + { + addr = "[::0]"; + proxyProtocol = true; + port = 444; + ssl = true; + } + { + addr = "[::0]"; + port = 443; + ssl = true; + } + { + addr = "[::0]"; + port = 80; + ssl = false; + } + # Private networking + { + addr = "127.0.0.1"; + port = 80; + ssl = false; + } + { + addr = "[::1]"; + port = 80; + ssl = false; + } + ]; - appendHttpConfig = '' - # Kurisu node - set_real_ip_from ${allowedUpstream}; - real_ip_header proxy_protocol; - ''; - }; - - # Move to nftables if firewall is enabled. - networking.nftables.enable = true; - networking.firewall.extraInputRules = '' - ip6 saddr ${allowedUpstream} tcp dport 444 accept + appendHttpConfig = '' + # Kurisu node + set_real_ip_from ${allowedUpstream}; + real_ip_header proxy_protocol; ''; }; - } + + # Move to nftables if firewall is enabled. + networking.nftables.enable = true; + networking.firewall.extraInputRules = '' + ip6 saddr ${allowedUpstream} tcp dport 444 accept + ''; + }; +} diff --git a/common/raito-vm.nix b/common/raito-vm.nix index a758605..cbbd4d2 100644 --- a/common/raito-vm.nix +++ b/common/raito-vm.nix @@ -1,7 +1,12 @@ -{ lib, config, ... }: +{ lib, config, ... }: let cfg = config.bagel.hardware.raito-vm; - inherit (lib) mkEnableOption mkIf mkOption types; + inherit (lib) + mkEnableOption + mkIf + mkOption + types + ; in { options.bagel.hardware.raito-vm = { diff --git a/common/ssh-keys.nix b/common/ssh-keys.nix index 47afa41..b92d19f 100644 --- a/common/ssh-keys.nix +++ b/common/ssh-keys.nix @@ -23,7 +23,9 @@ users = { delroth = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII3tjB4KYDok3KlWxdBp/yEmqhhmybd+w0VO4xUwLKKV" ]; - emilylange = [ "no-touch-required sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIL7jgq3i+N3gVJhs4shm7Kmw6dIocs2OuR0GBMG1RxfKAAAABHNzaDo=" ]; + emilylange = [ + "no-touch-required sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIL7jgq3i+N3gVJhs4shm7Kmw6dIocs2OuR0GBMG1RxfKAAAABHNzaDo=" + ]; hexchen = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINJ0tCxsEilAzV6LaNpUpcjzyEn4ptw8kFz3R+Z3YjEF hexchen@backup" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDI3T1eFS77URHZ/HVWkMOqx7W1U54zJtn9C7QWsHOtyH72i/4EVj8SxYqLllElh1kuKUXSUipPeEzVsipFVvfH0wEuTDgFffiSQ3a8lfUgdEBuoySwceEoPgc5deapkOmiDIDeeWlrRe3nqspLRrSWU1DirMxoFPbwqJXRvpl6qJPxRg+2IolDcXlZ6yxB4Vv48vzRfVzZNUz7Pjmy2ebU8PbDoFWL/S3m7yOzQpv3L7KYBz7+rkjuF3AU2vy6CAfIySkVpspZZLtkTGCIJF228ev0e8NvhuN6ZnjzXxVTQOy32HCdPdbBbicu0uHfZ5O7JX9DjGd8kk1r2dnZwwy/ hexchen@yubi5" @@ -40,7 +42,9 @@ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBLZxVITpJ8xbiCa/u2gjSSIupeiqOnRh+8tFIoVhCON" ]; k900 = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOi9vgVGs+S5kEsUqHPvyMMh1Q9gqL4TcbHoe5d73tun" ]; - lukegb = [ ''cert-authority,principals="lukegb" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEqNOwlR7Qa8cbGpDfSCOweDPbAGQOZIcoRgh6s/J8DR'' ]; + lukegb = [ + ''cert-authority,principals="lukegb" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEqNOwlR7Qa8cbGpDfSCOweDPbAGQOZIcoRgh6s/J8DR'' + ]; maxine = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILpWQfhNFdrxMTP/1DwBVuk49f3df9iH7Tbdu8ltIKjr" ]; raito = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaw9ihTG7ucB8P38XdalEWev8+q96e2yNm4B+/I9IJp" @@ -49,6 +53,8 @@ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKiXXYkhRh+s7ixZ8rvG8ntIqd6FELQ9hh7HoaHQJRPU" ]; thubrecht = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPM1jpXR7BWQa7Sed7ii3SbvIPRRlKb3G91qC0vOwfJn" ]; - yuka = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKath4/fDnlv/4fzxkPrQN1ttmoPRNu/m9bEtdPJBDfY cardno:16_933_242" ]; + yuka = [ + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKath4/fDnlv/4fzxkPrQN1ttmoPRNu/m9bEtdPJBDfY cardno:16_933_242" + ]; }; } diff --git a/common/sysadmin/default.nix b/common/sysadmin/default.nix index 5d7a661..31ad085 100644 --- a/common/sysadmin/default.nix +++ b/common/sysadmin/default.nix @@ -1,29 +1,34 @@ -{ pkgs, config, lib, ... }: +{ + pkgs, + config, + lib, + ... +}: let inherit (lib) mkIf mkEnableOption; cfg = config.bagel.sysadmin; in - { - options.bagel.sysadmin.enable = mkEnableOption "sysadmin tooling"; +{ + options.bagel.sysadmin.enable = mkEnableOption "sysadmin tooling"; - config = mkIf cfg.enable { - environment.systemPackages = with pkgs; [ - wget - vim - tmux - rsync - fd - ripgrep - pv - kitty.terminfo - config.boot.kernelPackages.perf - bcc - tcpdump - ncdu - # Useful to invoke `coredumpctl gdb` - gdb - htop - btop - ]; - }; - } + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + wget + vim + tmux + rsync + fd + ripgrep + pv + kitty.terminfo + config.boot.kernelPackages.perf + bcc + tcpdump + ncdu + # Useful to invoke `coredumpctl gdb` + gdb + htop + btop + ]; + }; +} diff --git a/common/zsh.nix b/common/zsh.nix index 4f3d696..e994fa0 100644 --- a/common/zsh.nix +++ b/common/zsh.nix @@ -1,4 +1,10 @@ -{ lib, pkgs, config, ... }: { +{ + lib, + pkgs, + config, + ... +}: +{ users.defaultUserShell = pkgs.zsh; programs.zsh = { enable = true; diff --git a/hosts/bagel-box/default.nix b/hosts/bagel-box/default.nix index 07f4057..dd3fd0a 100644 --- a/hosts/bagel-box/default.nix +++ b/hosts/bagel-box/default.nix @@ -9,7 +9,11 @@ boot.specialFileSystems = lib.mkForce { "/run/wrappers" = { fsType = "tmpfs"; - options = [ "nodev" "mode=755" "size=${config.security.wrapperDirSize}" ]; + options = [ + "nodev" + "mode=755" + "size=${config.security.wrapperDirSize}" + ]; }; }; @@ -24,13 +28,22 @@ nameservers = [ "2001:4860:4860::8844" ]; interfaces.host0.ipv6.addresses = [ - { address = "2001:bc8:38ee:100:100::1"; prefixLength = 64; } + { + address = "2001:bc8:38ee:100:100::1"; + prefixLength = 64; + } ]; interfaces.host1.ipv4.addresses = [ - { address = "172.16.100.2"; prefixLength = 24; } + { + address = "172.16.100.2"; + prefixLength = 24; + } ]; - defaultGateway = { address = "172.16.100.1"; interface = "host1"; }; + defaultGateway = { + address = "172.16.100.1"; + interface = "host1"; + }; firewall.allowPing = true; }; diff --git a/hosts/gerrit01/default.nix b/hosts/gerrit01/default.nix index 7dc7de9..625a62e 100755 --- a/hosts/gerrit01/default.nix +++ b/hosts/gerrit01/default.nix @@ -32,9 +32,7 @@ bagel.services.gerrit = { enable = true; - domains = [ - "cl.forkos.org" - ]; + domains = [ "cl.forkos.org" ]; canonicalDomain = "cl.forkos.org"; data = "/gerrit-data"; }; @@ -46,81 +44,93 @@ group = "git"; }; bagel.nixpkgs.one-way-sync = - let - mkNixpkgsJob = { timer, fromRefspec, localRefspec ? fromRefspec }: { - fromUri = "https://github.com/NixOS/nixpkgs"; - inherit fromRefspec localRefspec timer; - }; - mkLocalJob = { timer, fromRefspec, localRefspec }: { - fromUri = "https://cl.forkos.org/nixpkgs"; - inherit fromRefspec localRefspec timer; - }; + let + mkNixpkgsJob = + { + timer, + fromRefspec, + localRefspec ? fromRefspec, + }: + { + fromUri = "https://github.com/NixOS/nixpkgs"; + inherit fromRefspec localRefspec timer; + }; + mkLocalJob = + { + timer, + fromRefspec, + localRefspec, + }: + { + fromUri = "https://cl.forkos.org/nixpkgs"; + inherit fromRefspec localRefspec timer; + }; in - { - enable = true; + { + enable = true; - pushUrl = "ssh://ows_bot@cl.forkos.org:29418/nixpkgs"; - deployKeyPath = config.age.secrets.ows-deploy-key.path; + pushUrl = "ssh://ows_bot@cl.forkos.org:29418/nixpkgs"; + deployKeyPath = config.age.secrets.ows-deploy-key.path; - # Sync main -> staging-next -> staging - branches."main-to-staging-next" = mkLocalJob { - timer = "00/8:20:00"; # every 8 hours, 20 minutes past the full hour - fromRefspec = "main"; - localRefspec = "staging-next"; - }; - branches."staging-next-to-staging" = mkLocalJob { - timer = "00/8:40:00"; # every 8 hours, 40 minutes past the full hour - fromRefspec = "staging-next"; - localRefspec = "staging"; - }; + # Sync main -> staging-next -> staging + branches."main-to-staging-next" = mkLocalJob { + timer = "00/8:20:00"; # every 8 hours, 20 minutes past the full hour + fromRefspec = "main"; + localRefspec = "staging-next"; + }; + branches."staging-next-to-staging" = mkLocalJob { + timer = "00/8:40:00"; # every 8 hours, 40 minutes past the full hour + fromRefspec = "staging-next"; + localRefspec = "staging"; + }; - # Sync nixpkgs -> fork - branches."nixpkgs-master" = mkNixpkgsJob { - timer = "hourly"; - fromRefspec = "master"; - localRefspec = "main"; - }; + # Sync nixpkgs -> fork + branches."nixpkgs-master" = mkNixpkgsJob { + timer = "hourly"; + fromRefspec = "master"; + localRefspec = "main"; + }; - branches."nixpkgs-staging" = mkNixpkgsJob { - timer = "hourly"; - fromRefspec = "staging"; - }; + branches."nixpkgs-staging" = mkNixpkgsJob { + timer = "hourly"; + fromRefspec = "staging"; + }; - branches."nixpkgs-release-24.05" = mkNixpkgsJob { - timer = "hourly"; - fromRefspec = "release-24.05"; - }; + branches."nixpkgs-release-24.05" = mkNixpkgsJob { + timer = "hourly"; + fromRefspec = "release-24.05"; + }; - branches."nixpkgs-staging-24.05" = mkNixpkgsJob { - timer = "hourly"; - fromRefspec = "staging-24.05"; - }; + branches."nixpkgs-staging-24.05" = mkNixpkgsJob { + timer = "hourly"; + fromRefspec = "staging-24.05"; + }; - branches."nixpkgs-release-23.11" = mkNixpkgsJob { - timer = "hourly"; - fromRefspec = "release-23.11"; - }; + branches."nixpkgs-release-23.11" = mkNixpkgsJob { + timer = "hourly"; + fromRefspec = "release-23.11"; + }; - branches."nixpkgs-staging-23.11" = mkNixpkgsJob { - timer = "hourly"; - fromRefspec = "staging-23.11"; - }; + branches."nixpkgs-staging-23.11" = mkNixpkgsJob { + timer = "hourly"; + fromRefspec = "staging-23.11"; + }; - # Testing jobs for personal sandbox branches - branches."raito-unstable-sync" = { - fromUri = "https://github.com/NixOS/nixpkgs"; - fromRefspec = "nixos-unstable-small"; - localRefspec = "sandbox/raito/raito-unstable-small"; - timer = "*-*-* 12:00:00"; - }; + # Testing jobs for personal sandbox branches + branches."raito-unstable-sync" = { + fromUri = "https://github.com/NixOS/nixpkgs"; + fromRefspec = "nixos-unstable-small"; + localRefspec = "sandbox/raito/raito-unstable-small"; + timer = "*-*-* 12:00:00"; + }; - branches."raito-release-sync" = { - fromUri = "https://github.com/NixOS/nixpkgs"; - fromRefspec = "nixos-24.05"; - localRefspec = "sandbox/raito/raito-nixos-24.05"; - timer = "daily"; + branches."raito-release-sync" = { + fromUri = "https://github.com/NixOS/nixpkgs"; + fromRefspec = "nixos-24.05"; + localRefspec = "sandbox/raito/raito-nixos-24.05"; + timer = "daily"; + }; }; - }; i18n.defaultLocale = "fr_FR.UTF-8"; diff --git a/hosts/git/default.nix b/hosts/git/default.nix index 4399485..2d860e6 100644 --- a/hosts/git/default.nix +++ b/hosts/git/default.nix @@ -1,6 +1,6 @@ let ipv6 = { - openssh ="2001:bc8:38ee:100:1000::41"; + openssh = "2001:bc8:38ee:100:1000::41"; forgejo = "2001:bc8:38ee:100:1000::40"; }; in @@ -27,9 +27,7 @@ in # Add one additional IPv6, so we can have both OpenSSH and # Forgejo's built-in server bind on port :22. systemd.network.networks."10-wan".networkConfig.Address = [ "${ipv6.openssh}/64" ]; - services.openssh.listenAddresses = [{ - addr = "[${ipv6.openssh}]"; - }]; + services.openssh.listenAddresses = [ { addr = "[${ipv6.openssh}]"; } ]; # Defaults to network.target, but networkd may take a while to settle and set up # the required (additional) IPv6 address, leading to sshd to not being able to # bind to the requested IP, crashing 5 times and running into the default diff --git a/hosts/meta01/default.nix b/hosts/meta01/default.nix index a465f0f..3b949f3 100755 --- a/hosts/meta01/default.nix +++ b/hosts/meta01/default.nix @@ -27,9 +27,7 @@ bagel.services.grapevine.enable = true; bagel.services.hookshot = { enable = true; - admins = [ - "@k900:0upti.me" - ]; + admins = [ "@k900:0upti.me" ]; }; i18n.defaultLocale = "fr_FR.UTF-8"; diff --git a/hosts/wob-vpn-gw/default.nix b/hosts/wob-vpn-gw/default.nix index 80a7655..51fba3b 100644 --- a/hosts/wob-vpn-gw/default.nix +++ b/hosts/wob-vpn-gw/default.nix @@ -1,25 +1,29 @@ { pkgs, lib, ... }: { - imports = [ - ./netboot.nix - ]; + imports = [ ./netboot.nix ]; ###### Hardware ###### - boot.initrd.availableKernelModules = [ "xhci_pci" "ahci" "ehci_pci" "sd_mod" "sdhci_pci" ]; + boot.initrd.availableKernelModules = [ + "xhci_pci" + "ahci" + "ehci_pci" + "sd_mod" + "sdhci_pci" + ]; boot.kernelModules = [ "kvm-amd" ]; boot.loader.grub.device = "/dev/sda"; - fileSystems."/" = - { device = "/dev/disk/by-uuid/58688a5c-e3ce-4868-804b-4e34d1370f36"; - fsType = "f2fs"; - }; + fileSystems."/" = { + device = "/dev/disk/by-uuid/58688a5c-e3ce-4868-804b-4e34d1370f36"; + fsType = "f2fs"; + }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/38caa628-3b6d-4fb4-8767-beee09a196a6"; - fsType = "ext2"; - }; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/38caa628-3b6d-4fb4-8767-beee09a196a6"; + fsType = "ext2"; + }; nixpkgs.hostPlatform = "x86_64-linux"; @@ -65,29 +69,36 @@ }; }; }; - networks = { - "40-enp1s0" = { - name = "enp1s0"; - bond = [ "uplink" ]; - }; - "40-enp2s0" = { - name = "enp2s0"; - bond = [ "uplink" ]; - }; - "40-enp3s0" = { - name = "enp3s0"; - bond = [ "oob" ]; - }; - "40-enp4s0" = { - name = "enp4s0"; - bond = [ "oob" ]; - }; - } // lib.listToAttrs (map (x: lib.nameValuePair "40-bmc${toString x}" { - name = "bmc${toString x}"; - address = [ "192.168.1.${toString (x*4 + 1)}/30" ]; - #address = [ "192.168.${toString x}.1/24" ]; - networkConfig.DHCPServer = true; - }) (lib.genList lib.id 12)); + networks = + { + "40-enp1s0" = { + name = "enp1s0"; + bond = [ "uplink" ]; + }; + "40-enp2s0" = { + name = "enp2s0"; + bond = [ "uplink" ]; + }; + "40-enp3s0" = { + name = "enp3s0"; + bond = [ "oob" ]; + }; + "40-enp4s0" = { + name = "enp4s0"; + bond = [ "oob" ]; + }; + } + // lib.listToAttrs ( + map ( + x: + lib.nameValuePair "40-bmc${toString x}" { + name = "bmc${toString x}"; + address = [ "192.168.1.${toString (x * 4 + 1)}/30" ]; + #address = [ "192.168.${toString x}.1/24" ]; + networkConfig.DHCPServer = true; + } + ) (lib.genList lib.id 12) + ); }; networking.nftables.enable = true; @@ -95,10 +106,15 @@ iifname { "bmc*" } meta nfproto ipv4 udp dport 67 accept comment "DHCP server" ''; - networking.vlans = lib.listToAttrs (map (x: lib.nameValuePair "bmc${toString x}" { - interface = "oob"; - id = 101 + x; - }) (lib.genList lib.id 12)); + networking.vlans = lib.listToAttrs ( + map ( + x: + lib.nameValuePair "bmc${toString x}" { + interface = "oob"; + id = 101 + x; + } + ) (lib.genList lib.id 12) + ); networking.interfaces = { uplink = { @@ -111,7 +127,10 @@ }; }; - networking.defaultGateway6 = { interface = "uplink"; address = "2a01:584:11::1"; }; + networking.defaultGateway6 = { + interface = "uplink"; + address = "2a01:584:11::1"; + }; networking.hostName = "vpn-gw"; networking.domain = "wob01.infra.forkos.org"; diff --git a/hosts/wob-vpn-gw/netboot.nix b/hosts/wob-vpn-gw/netboot.nix index 08d39ae..60c9871 100644 --- a/hosts/wob-vpn-gw/netboot.nix +++ b/hosts/wob-vpn-gw/netboot.nix @@ -1,4 +1,11 @@ -{ config, lib, pkgs, nodes, modulesPath, ... }: +{ + config, + lib, + pkgs, + nodes, + modulesPath, + ... +}: # The way the connection is established is specific to the wob01 site and the Intel S2600KPR blades. # Proper netboot is not possible, because while the blades and the APU board (which is the netboot @@ -10,8 +17,11 @@ let netboot-server-ip = "2a01:584:11::2"; - netbootNodes = lib.filterAttrs (_: node: node.config.bagel.baremetal.builders.enable && node.config.bagel.baremetal.builders.netboot) nodes; -in { + netbootNodes = lib.filterAttrs ( + _: node: node.config.bagel.baremetal.builders.enable && node.config.bagel.baremetal.builders.netboot + ) nodes; +in +{ assertions = [ { @@ -23,19 +33,23 @@ in { } ]; - systemd.services = lib.mapAttrs' (nodename: node: let - bmcIp = "192.168.1.${toString (node.config.bagel.baremetal.builders.num * 4 + 2)}"; - notipxe = node.config.system.build.notipxe.config.system.build.usbImage; - in lib.nameValuePair "iusb-spoof-${nodename}" { - wantedBy = [ "multi-user.target" ]; - serviceConfig = { - Restart = "always"; - }; - script = '' - AUTH_TOKEN=$(${pkgs.iusb-spoof}/bin/make-token ${bmcIp}) - exec ${pkgs.iusb-spoof}/bin/iusb-spoof -r ${bmcIp} 5123 $AUTH_TOKEN ${notipxe} - ''; - }) netbootNodes; + systemd.services = lib.mapAttrs' ( + nodename: node: + let + bmcIp = "192.168.1.${toString (node.config.bagel.baremetal.builders.num * 4 + 2)}"; + notipxe = node.config.system.build.notipxe.config.system.build.usbImage; + in + lib.nameValuePair "iusb-spoof-${nodename}" { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Restart = "always"; + }; + script = '' + AUTH_TOKEN=$(${pkgs.iusb-spoof}/bin/make-token ${bmcIp}) + exec ${pkgs.iusb-spoof}/bin/iusb-spoof -r ${bmcIp} 5123 $AUTH_TOKEN ${notipxe} + ''; + } + ) netbootNodes; # Since the builders are stateless, they can not store their ssh hostkeys networking.firewall.allowedTCPPorts = [ 80 ]; # for ACME @@ -49,15 +63,19 @@ in { virtualHosts."vpn-gw.wob01.infra.forkos.org" = { enableACME = true; forceSSL = true; - locations = lib.mapAttrs' (nodename: node: let - ip = "2a01:584:11::1:${toString node.config.bagel.baremetal.builders.num}"; - in lib.nameValuePair "/${nodename}/" { - root = "/var/www"; - extraConfig = '' - allow ${ip}; - deny all; - ''; - }) netbootNodes; + locations = lib.mapAttrs' ( + nodename: node: + let + ip = "2a01:584:11::1:${toString node.config.bagel.baremetal.builders.num}"; + in + lib.nameValuePair "/${nodename}/" { + root = "/var/www"; + extraConfig = '' + allow ${ip}; + deny all; + ''; + } + ) netbootNodes; }; }; } diff --git a/lib/colmena-wrapper.nix b/lib/colmena-wrapper.nix index 87c1f1d..41f9e41 100644 --- a/lib/colmena-wrapper.nix +++ b/lib/colmena-wrapper.nix @@ -1,10 +1,7 @@ # A wrapper for colmena that prevents accidentally deploying changes without # having pulled. { colmena, runCommandNoCC }: -runCommandNoCC "colmena-wrapper" -{ - env.colmena = "${colmena}/bin/colmena"; -} '' +runCommandNoCC "colmena-wrapper" { env.colmena = "${colmena}/bin/colmena"; } '' mkdir -p $out ln -s ${colmena}/share $out/share mkdir $out/bin diff --git a/overlays/default.nix b/overlays/default.nix index 5162ed7..fa4987c 100644 --- a/overlays/default.nix +++ b/overlays/default.nix @@ -1,6 +1,6 @@ [ (final: prev: { - iusb-spoof = final.callPackage ./iusb-spoof.nix {}; - u-root = final.callPackage ./u-root {}; + iusb-spoof = final.callPackage ./iusb-spoof.nix { }; + u-root = final.callPackage ./u-root { }; }) ] diff --git a/overlays/iusb-spoof.nix b/overlays/iusb-spoof.nix index 9235e52..02bb879 100644 --- a/overlays/iusb-spoof.nix +++ b/overlays/iusb-spoof.nix @@ -1,4 +1,8 @@ -{ rustPlatform, python3, makeWrapper }: +{ + rustPlatform, + python3, + makeWrapper, +}: let pythonEnv = python3.withPackages (p: with p; [ requests ]); in diff --git a/overlays/u-root/default.nix b/overlays/u-root/default.nix index acddbfb..01a5a7c 100644 --- a/overlays/u-root/default.nix +++ b/overlays/u-root/default.nix @@ -11,9 +11,7 @@ buildGoModule rec { hash = "sha256-8zA3pHf45MdUcq/MA/mf0KCTxB1viHieU/oigYwIPgo="; }; - patches = [ - ./u-root-allow-https.patch - ]; + patches = [ ./u-root-allow-https.patch ]; vendorHash = null; doCheck = false; diff --git a/secrets.nix b/secrets.nix index caca9dc..dcca500 100644 --- a/secrets.nix +++ b/secrets.nix @@ -12,7 +12,10 @@ let mimir-webhook-url = [ machines.meta01 ]; grafana-oauth-secret = [ machines.meta01 ]; loki-environment = [ machines.meta01 ]; - gerrit-prometheus-bearer-token = [ machines.gerrit01 machines.meta01 ]; + gerrit-prometheus-bearer-token = [ + machines.gerrit01 + machines.meta01 + ]; buildbot-worker-password = [ machines.buildbot ]; buildbot-oauth-secret = [ machines.buildbot ]; @@ -31,9 +34,9 @@ let ows-deploy-key = [ machines.gerrit01 ]; }; in - builtins.listToAttrs ( - map (secretName: { - name = "secrets/${secretName}.age"; - value.publicKeys = secrets."${secretName}" ++ commonKeys; - }) (builtins.attrNames secrets) - ) +builtins.listToAttrs ( + map (secretName: { + name = "secrets/${secretName}.age"; + value.publicKeys = secrets."${secretName}" ++ commonKeys; + }) (builtins.attrNames secrets) +) diff --git a/services/baremetal-builder/assignments.nix b/services/baremetal-builder/assignments.nix index e1a27de..f4f896e 100644 --- a/services/baremetal-builder/assignments.nix +++ b/services/baremetal-builder/assignments.nix @@ -1,29 +1,61 @@ # This file contains information on which builder(s) are providing how many # job slots and providing which nix features let - genBuilders = { offset ? 0, count, f }: builtins.genList (x: rec { name = "builder-${toString (offset + x)}"; value = f name; }) count; -in builtins.listToAttrs ( + genBuilders = + { + offset ? 0, + count, + f, + }: + builtins.genList (x: rec { + name = "builder-${toString (offset + x)}"; + value = f name; + }) count; +in +builtins.listToAttrs ( # The first 8 builders are general purpose hydra builders - genBuilders { count = 8; f = name: { - cores = 8; - max-jobs = 8; - supported-features = [ "kvm" "nixos-test" ]; - required-features = [ ]; - }; } + genBuilders { + count = 8; + f = name: { + cores = 8; + max-jobs = 8; + supported-features = [ + "kvm" + "nixos-test" + ]; + required-features = [ ]; + }; + } ++ - # The last 2 builders are exclusively for big-parallel - genBuilders { offset = 8; count = 2; f = name: { - cores = 20; - max-jobs = 1; - supported-features = [ "kvm" "nixos-test" "big-parallel" ]; - required-features = [ "big-parallel" ]; - }; } + # The last 2 builders are exclusively for big-parallel + genBuilders { + offset = 8; + count = 2; + f = name: { + cores = 20; + max-jobs = 1; + supported-features = [ + "kvm" + "nixos-test" + "big-parallel" + ]; + required-features = [ "big-parallel" ]; + }; + } ++ - # These are not currently used for hydra - genBuilders { offset = 10; count = 2; f = name: { - cores = 8; - max-jobs = 8; - supported-features = [ "kvm" "nixos-test" "big-parallel" ]; - required-features = [ ]; - }; } + # These are not currently used for hydra + genBuilders { + offset = 10; + count = 2; + f = name: { + cores = 8; + max-jobs = 8; + supported-features = [ + "kvm" + "nixos-test" + "big-parallel" + ]; + required-features = [ ]; + }; + } ) diff --git a/services/baremetal-builder/default.nix b/services/baremetal-builder/default.nix index 0b9de91..a63267a 100644 --- a/services/baremetal-builder/default.nix +++ b/services/baremetal-builder/default.nix @@ -1,4 +1,9 @@ -{ pkgs, lib, config, ... }: +{ + pkgs, + lib, + config, + ... +}: let cfg = config.bagel.baremetal.builders; in @@ -10,14 +15,18 @@ in bagel.baremetal.builders = { enable = lib.mkEnableOption "baremetal bagel oven"; netboot = lib.mkEnableOption "netboot"; - num = lib.mkOption { - type = lib.types.int; - }; + num = lib.mkOption { type = lib.types.int; }; }; }; config = lib.mkIf cfg.enable { - boot.initrd.availableKernelModules = [ "ahci" "ehci_pci" "usb_storage" "usbhid" "sd_mod" ]; + boot.initrd.availableKernelModules = [ + "ahci" + "ehci_pci" + "usb_storage" + "usbhid" + "sd_mod" + ]; boot.initrd.kernelModules = [ "dm-snapshot" ]; users.users.builder = { @@ -44,7 +53,10 @@ in ]; }; nix.settings = { - trusted-users = [ "builder" "buildbot" ]; + trusted-users = [ + "builder" + "buildbot" + ]; inherit ((import ./assignments.nix).${config.networking.hostName}) max-jobs cores; }; @@ -68,14 +80,17 @@ in "/boot" = { device = "/dev/disk/by-label/BOOT"; fsType = "vfat"; - options = [ "fmask=0022" "dmask=0022" ]; + options = [ + "fmask=0022" + "dmask=0022" + ]; }; }) { "/mnt" = { device = "/dev/disk/by-label/hydra"; fsType = "xfs"; - options = ["logbsize=256k"]; + options = [ "logbsize=256k" ]; }; # We want the tmp filesystem on the same filesystem as the hydra store, so that builds can use reflinks @@ -89,7 +104,7 @@ in swapDevices = lib.optionals (!cfg.netboot) [ { device = "/swapfile"; - size = 50 * 1024; # 50GiB + size = 50 * 1024; # 50GiB } ]; @@ -132,9 +147,15 @@ in }; }; networking.interfaces.uplink.ipv6.addresses = [ - { address = "2a01:584:11::1:${toString cfg.num}"; prefixLength = 64; } + { + address = "2a01:584:11::1:${toString cfg.num}"; + prefixLength = 64; + } ]; - networking.defaultGateway6 = { interface = "uplink"; address = "2a01:584:11::1"; }; + networking.defaultGateway6 = { + interface = "uplink"; + address = "2a01:584:11::1"; + }; deployment.targetHost = "2a01:584:11::1:${toString cfg.num}"; deployment.tags = [ "builders" ]; diff --git a/services/baremetal-builder/netboot.nix b/services/baremetal-builder/netboot.nix index 4f6782d..9ccca89 100644 --- a/services/baremetal-builder/netboot.nix +++ b/services/baremetal-builder/netboot.nix @@ -1,4 +1,11 @@ -{ modulesPath, pkgs, lib, config, extendModules, ... }@node: +{ + modulesPath, + pkgs, + lib, + config, + extendModules, + ... +}@node: let cfg = config.bagel.baremetal.builders; in @@ -27,13 +34,25 @@ in # u-root pxeboot tool and kexec into the final netbooted system. notipxe = import (modulesPath + "/..") { system = "x86_64-linux"; - configuration = + configuration = { pkgs, config, ... }: { system.stateVersion = "24.11"; - boot.initrd.availableKernelModules = [ "ahci" "ehci_pci" "usb_storage" "usbhid" "sd_mod" "igb" "bonding" ]; - boot.kernelParams = [ "console=ttyS0,115200" "panic=1" "boot.panic_on_fail" ]; + boot.initrd.availableKernelModules = [ + "ahci" + "ehci_pci" + "usb_storage" + "usbhid" + "sd_mod" + "igb" + "bonding" + ]; + boot.kernelParams = [ + "console=ttyS0,115200" + "panic=1" + "boot.panic_on_fail" + ]; #boot.initrd.systemd.emergencyAccess = true; networking.hostName = "${node.config.networking.hostName}-boot"; nixpkgs.overlays = import ../../overlays; @@ -72,64 +91,84 @@ in ''; # Provide a bootable USB drive image - system.build.usbImage = pkgs.callPackage ({ stdenv, runCommand, dosfstools, e2fsprogs, mtools, libfaketime, util-linux, nukeReferences }: - runCommand "boot-img-${node.config.networking.hostName}" { - nativeBuildInputs = [ dosfstools e2fsprogs libfaketime mtools util-linux ]; - outputs = [ "out" "firmware_part" ]; - } '' - export img=$out - truncate -s 40M $img + system.build.usbImage = pkgs.callPackage ( + { + stdenv, + runCommand, + dosfstools, + e2fsprogs, + mtools, + libfaketime, + util-linux, + nukeReferences, + }: + runCommand "boot-img-${node.config.networking.hostName}" + { + nativeBuildInputs = [ + dosfstools + e2fsprogs + libfaketime + mtools + util-linux + ]; + outputs = [ + "out" + "firmware_part" + ]; + } + '' + export img=$out + truncate -s 40M $img - sfdisk $img < firmware/loader/loader.conf << EOF - default foo - EOF - cat > firmware/loader/entries/default.conf << EOF - title Default - linux /EFI/${pkgs.stdenv.hostPlatform.linux-kernel.target} - initrd /EFI/initrd - options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} - EOF - cp ${config.system.build.kernel}/${pkgs.stdenv.hostPlatform.linux-kernel.target} firmware/EFI/${pkgs.stdenv.hostPlatform.linux-kernel.target} - cp ${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile} firmware/EFI/initrd + cat > firmware/loader/loader.conf << EOF + default foo + EOF + cat > firmware/loader/entries/default.conf << EOF + title Default + linux /EFI/${pkgs.stdenv.hostPlatform.linux-kernel.target} + initrd /EFI/initrd + options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} + EOF + cp ${config.system.build.kernel}/${pkgs.stdenv.hostPlatform.linux-kernel.target} firmware/EFI/${pkgs.stdenv.hostPlatform.linux-kernel.target} + cp ${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile} firmware/EFI/initrd - find firmware -exec touch --date=2000-01-01 {} + - # Copy the populated /boot/firmware into the SD image - cd firmware - # Force a fixed order in mcopy for better determinism, and avoid file globbing - for d in $(find . -type d -mindepth 1 | sort); do - faketime "2000-01-01 00:00:00" mmd -i ../firmware_part.img "::/$d" - done - for f in $(find . -type f | sort); do - mcopy -pvm -i ../firmware_part.img "$f" "::/$f" - done - cd .. + find firmware -exec touch --date=2000-01-01 {} + + # Copy the populated /boot/firmware into the SD image + cd firmware + # Force a fixed order in mcopy for better determinism, and avoid file globbing + for d in $(find . -type d -mindepth 1 | sort); do + faketime "2000-01-01 00:00:00" mmd -i ../firmware_part.img "::/$d" + done + for f in $(find . -type f | sort); do + mcopy -pvm -i ../firmware_part.img "$f" "::/$f" + done + cd .. - # Verify the FAT partition before copying it. - fsck.vfat -vn firmware_part.img - dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS + # Verify the FAT partition before copying it. + fsck.vfat -vn firmware_part.img + dd conv=notrunc if=firmware_part.img of=$img seek=$START count=$SECTORS - cp firmware_part.img $firmware_part - '' - ) {}; - } - ; + cp firmware_part.img $firmware_part + '' + ) { }; + }; }; # This is the config which will actually be booted @@ -145,10 +184,11 @@ in ]; }; # A derivation combining all the artifacts required for netbooting for the hydra job - netbootDir = let - kernelTarget = pkgs.stdenv.hostPlatform.linux-kernel.target; - build = config.system.build.netbootVariant.config.system.build; - in + netbootDir = + let + kernelTarget = pkgs.stdenv.hostPlatform.linux-kernel.target; + build = config.system.build.netbootVariant.config.system.build; + in pkgs.symlinkJoin { name = "netboot"; paths = [ diff --git a/services/buildbot/default.nix b/services/buildbot/default.nix index 4cd482e..0c80e86 100644 --- a/services/buildbot/default.nix +++ b/services/buildbot/default.nix @@ -9,24 +9,33 @@ let cfg = config.bagel.services.buildbot; cfgGerrit = nodes.gerrit01.config.bagel.services.gerrit; ssh-keys = import ../../common/ssh-keys.nix; - inherit (lib) mkEnableOption mkOption mkIf types; + inherit (lib) + mkEnableOption + mkOption + mkIf + types + ; in { options.bagel.services.buildbot = { enable = mkEnableOption "Buildbot"; - domain = mkOption { - type = types.str; - }; + domain = mkOption { type = types.str; }; builders = mkOption { type = types.listOf types.str; description = "List of builders to configure for Buildbot"; - example = [ "builder-2" "builder-3" ]; + example = [ + "builder-2" + "builder-3" + ]; }; }; config = mkIf cfg.enable { - networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall.allowedTCPPorts = [ + 80 + 443 + ]; age.secrets.buildbot-worker-password.file = ../../secrets/buildbot-worker-password.age; age.secrets.buildbot-oauth-secret.file = ../../secrets/buildbot-oauth-secret.age; age.secrets.buildbot-workers.file = ../../secrets/buildbot-workers.age; @@ -56,18 +65,17 @@ in workerPasswordFile = config.age.secrets.buildbot-worker-password.path; # All credits to eldritch horrors for this beauty. workerArchitectures = - { - # nix-eval-jobs runs under a lock, error reports do not (but are cheap) - other = 8; - } // ( - lib.filterAttrs - (n: v: lib.elem n config.services.buildbot-nix.coordinator.buildSystems) - (lib.zipAttrsWith - (_: lib.foldl' lib.add 0) - (lib.concatMap - (m: map (s: { ${s} = m.maxJobs; }) m.systems) - config.services.buildbot-nix.coordinator.buildMachines)) - ); + { + # nix-eval-jobs runs under a lock, error reports do not (but are cheap) + other = 8; + } + // (lib.filterAttrs (n: v: lib.elem n config.services.buildbot-nix.coordinator.buildSystems) ( + lib.zipAttrsWith (_: lib.foldl' lib.add 0) ( + lib.concatMap ( + m: map (s: { ${s} = m.maxJobs; }) m.systems + ) config.services.buildbot-nix.coordinator.buildMachines + ) + )); }; services.buildbot-nix.coordinator = { @@ -90,28 +98,23 @@ in # we can replace all of this with automatic localworker generation on buildbot-nix side. workersFile = config.age.secrets.buildbot-workers.path; - allowedOrigins = [ - "*.forkos.org" - ]; + allowedOrigins = [ "*.forkos.org" ]; # TODO(raito): is that really necessary when we can just collect buildMachines' systems? - buildSystems = [ - "x86_64-linux" - ]; + buildSystems = [ "x86_64-linux" ]; buildMachines = map (n: { - hostName = nodes.${n}.config.networking.fqdn; - protocol = "ssh-ng"; - # Follows Hydra. - maxJobs = 8; - sshKey = config.age.secrets.buildbot-remote-builder-key.path; - sshUser = "buildbot"; - systems = [ "x86_64-linux" ]; - supportedFeatures = nodes.${n}.config.nix.settings.system-features; - # Contrary to how Nix works, here we can specify non-base64 public host keys. - publicHostKey = ssh-keys.machines.${n}; - } - ) cfg.builders; + hostName = nodes.${n}.config.networking.fqdn; + protocol = "ssh-ng"; + # Follows Hydra. + maxJobs = 8; + sshKey = config.age.secrets.buildbot-remote-builder-key.path; + sshUser = "buildbot"; + systems = [ "x86_64-linux" ]; + supportedFeatures = nodes.${n}.config.nix.settings.system-features; + # Contrary to how Nix works, here we can specify non-base64 public host keys. + publicHostKey = ssh-keys.machines.${n}; + }) cfg.builders; gerrit = { domain = cfgGerrit.canonicalDomain; diff --git a/services/forgejo/default.nix b/services/forgejo/default.nix index a756e43..a20643c 100644 --- a/services/forgejo/default.nix +++ b/services/forgejo/default.nix @@ -1,18 +1,25 @@ -{ pkgs, lib, config, ... }: - +{ + pkgs, + lib, + config, + ... +}: let cfg = config.bagel.services.forgejo; - inherit (lib) mkIf mkEnableOption mkOption types; + inherit (lib) + mkIf + mkEnableOption + mkOption + types + ; domain = "git.forkos.org"; in { options.bagel.services.forgejo = { enable = mkEnableOption "Forgejo"; - sshBindAddr = mkOption { - type = types.str; - }; + sshBindAddr = mkOption { type = types.str; }; }; config = mkIf cfg.enable { @@ -116,8 +123,14 @@ in # start Forgejo *after* sshd.service, so in case Forgejo tries to wildcard bind :22 due to # a bug or whatever, we don't lose OpenSSH in a race. - wants = [ "sshd.service" "redis-forgejo.service" ]; - requires = [ "sshd.service" "redis-forgejo.service" ]; + wants = [ + "sshd.service" + "redis-forgejo.service" + ]; + requires = [ + "sshd.service" + "redis-forgejo.service" + ]; }; services.redis.servers.forgejo = { diff --git a/services/gerrit/default.nix b/services/gerrit/default.nix index 7b2c72b..429f0f5 100644 --- a/services/gerrit/default.nix +++ b/services/gerrit/default.nix @@ -1,9 +1,20 @@ # Gerrit configuration for the Nixpkgs monorepo # Inspired from TVL configuration. -{ pkgs, config, lib, ... }: +{ + pkgs, + config, + lib, + ... +}: let - inherit (lib) mkEnableOption mkIf mkOption types head; + inherit (lib) + mkEnableOption + mkIf + mkOption + types + head + ; cfgGerrit = config.services.gerrit; cfg = config.bagel.services.gerrit; @@ -53,7 +64,7 @@ in isSystemUser = true; group = "git"; }; - users.groups.git = {}; + users.groups.git = { }; services.gerrit = { enable = true; @@ -74,20 +85,22 @@ in oauth metrics-reporter-prometheus # Buildbot checks plugin (writeText because services.gerrit.plugins expects packages) - (pkgs.runCommand "checks.js" { - BASE_URI = builtins.toJSON "https://buildbot.forkos.org"; - SUPPORTED_PROJECTS = builtins.toJSON [ - "infra" - "nixpkgs" - "buildbot-test" - ]; - } - '' - echo "configuring buildbot checks plugin for $BASE_URI with $SUPPORTED_PROJECTS project list" - substitute ${./checks.js} $out \ - --replace-fail "@BASE_URI@" "$BASE_URI" \ - --replace-fail "@SUPPORTED_PROJECTS@" "$SUPPORTED_PROJECTS" - '') + (pkgs.runCommand "checks.js" + { + BASE_URI = builtins.toJSON "https://buildbot.forkos.org"; + SUPPORTED_PROJECTS = builtins.toJSON [ + "infra" + "nixpkgs" + "buildbot-test" + ]; + } + '' + echo "configuring buildbot checks plugin for $BASE_URI with $SUPPORTED_PROJECTS project list" + substitute ${./checks.js} $out \ + --replace-fail "@BASE_URI@" "$BASE_URI" \ + --replace-fail "@SUPPORTED_PROJECTS@" "$SUPPORTED_PROJECTS" + '' + ) ]; package = pkgs.gerrit; @@ -251,7 +264,7 @@ in age.secrets.gerrit-prometheus-bearer-token.file = ../../secrets/gerrit-prometheus-bearer-token.age; bagel.monitoring.grafana-agent.exporters.gerrit = { - port = 4778; # grrt + port = 4778; # grrt bearerTokenFile = config.age.secrets.gerrit-prometheus-bearer-token.path; scrapeConfig.metrics_path = "/plugins/metrics-reporter-prometheus/metrics"; }; diff --git a/services/gerrit/one-way-sync.nix b/services/gerrit/one-way-sync.nix index 39570b0..3cf53a8 100644 --- a/services/gerrit/one-way-sync.nix +++ b/services/gerrit/one-way-sync.nix @@ -1,59 +1,90 @@ -{ lib, config, pkgs, ... }: +{ + lib, + config, + pkgs, + ... +}: let cfg = config.bagel.nixpkgs.one-way-sync; - inherit (lib) mkIf mkOption mkEnableOption types mapAttrs'; + inherit (lib) + mkIf + mkOption + mkEnableOption + types + mapAttrs' + ; - mkSyncTimer = name: { timer, ... }: { - wantedBy = [ "timers.target" ]; + mkSyncTimer = + name: + { timer, ... }: + { + wantedBy = [ "timers.target" ]; - timerConfig = { - OnCalendar = timer; - Persistent = true; - Unit = "ows-${name}.service"; + timerConfig = { + OnCalendar = timer; + Persistent = true; + Unit = "ows-${name}.service"; + }; }; - }; - mkSyncService = name: { fromUri, fromRefspec, localRefspec, ... }: { - path = [ pkgs.gitFull pkgs.openssh pkgs.lix ]; - script = '' - set -xe - RUNTIME_DIRECTORY="/run/onewaysync-${name}" - trap "git worktree remove -f "$RUNTIME_DIRECTORY"/${name}" EXIT + mkSyncService = + name: + { + fromUri, + fromRefspec, + localRefspec, + ... + }: + { + path = [ + pkgs.gitFull + pkgs.openssh + pkgs.lix + ]; + script = + '' + set -xe + RUNTIME_DIRECTORY="/run/onewaysync-${name}" + trap "git worktree remove -f "$RUNTIME_DIRECTORY"/${name}" EXIT - if [ ! -d "/var/lib/onewaysync/nixpkgs" ]; then - echo "First run, synchronizing nixpkgs..." - git clone https://cl.forkos.org/nixpkgs /var/lib/onewaysync/nixpkgs - fi + if [ ! -d "/var/lib/onewaysync/nixpkgs" ]; then + echo "First run, synchronizing nixpkgs..." + git clone https://cl.forkos.org/nixpkgs /var/lib/onewaysync/nixpkgs + fi - cd /var/lib/onewaysync/nixpkgs - echo "Syncing ${fromUri}:${fromRefspec} to ${cfg.pushUrl}:refs/heads/${localRefspec}" - echo "Current ref: $EXPECTED_REF" - git worktree add -f "$RUNTIME_DIRECTORY"/${name} refs/remotes/origin/${localRefspec} - cd "$RUNTIME_DIRECTORY"/${name} - git pull origin ${localRefspec} --no-rebase - EXPECTED_REF=$(git rev-list refs/remotes/origin/${localRefspec} | head -1) - git config user.name Fork-o-Tron - git config user.email noreply@forkos.org - git fetch ${fromUri} ${fromRefspec} - '' + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) '' - OLD_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY") - '' + '' - git merge FETCH_HEAD - '' + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) '' - NEW_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY") - # Do not allow auto-merging a staging iteration - test "$OLD_STDENV" = "$NEW_STDENV" - '' + '' - GIT_SSH_COMMAND='ssh -i ${cfg.deployKeyPath}' git push ${cfg.pushUrl} HEAD:refs/heads/${localRefspec} - ''; - serviceConfig = { - User = "git"; - Group = "git"; - Type = "oneshot"; - RuntimeDirectory = "onewaysync-${name}"; - WorkingDirectory = "/run/onewaysync-${name}"; - StateDirectory = "onewaysync"; + cd /var/lib/onewaysync/nixpkgs + echo "Syncing ${fromUri}:${fromRefspec} to ${cfg.pushUrl}:refs/heads/${localRefspec}" + echo "Current ref: $EXPECTED_REF" + git worktree add -f "$RUNTIME_DIRECTORY"/${name} refs/remotes/origin/${localRefspec} + cd "$RUNTIME_DIRECTORY"/${name} + git pull origin ${localRefspec} --no-rebase + EXPECTED_REF=$(git rev-list refs/remotes/origin/${localRefspec} | head -1) + git config user.name Fork-o-Tron + git config user.email noreply@forkos.org + git fetch ${fromUri} ${fromRefspec} + '' + + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) '' + OLD_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY") + '' + + '' + git merge FETCH_HEAD + '' + + lib.optionalString (!(lib.hasInfix "staging" localRefspec)) '' + NEW_STDENV=$(nix eval -f . stdenv.outPath --store "$RUNTIME_DIRECTORY") + # Do not allow auto-merging a staging iteration + test "$OLD_STDENV" = "$NEW_STDENV" + '' + + '' + GIT_SSH_COMMAND='ssh -i ${cfg.deployKeyPath}' git push ${cfg.pushUrl} HEAD:refs/heads/${localRefspec} + ''; + serviceConfig = { + User = "git"; + Group = "git"; + Type = "oneshot"; + RuntimeDirectory = "onewaysync-${name}"; + WorkingDirectory = "/run/onewaysync-${name}"; + StateDirectory = "onewaysync"; + }; }; - }; in { options.bagel.nixpkgs.one-way-sync = { @@ -84,35 +115,39 @@ in }; branches = mkOption { - type = types.attrsOf (types.submodule ({ ... }: - { - options = { - name = mkOption { - type = types.str; - description = "User-friendly name"; - }; + type = types.attrsOf ( + types.submodule ( + { ... }: + { + options = { + name = mkOption { + type = types.str; + description = "User-friendly name"; + }; - fromUri = mkOption { - type = types.str; - description = "Git URI from which we need to sync"; - }; + fromUri = mkOption { + type = types.str; + description = "Git URI from which we need to sync"; + }; - fromRefspec = mkOption { - type = types.str; - description = "refspec for the fetch"; - }; + fromRefspec = mkOption { + type = types.str; + description = "refspec for the fetch"; + }; - localRefspec = mkOption { - type = types.str; - default = "local refspec in the local repository to get the expected reference and avoid stale info"; - }; + localRefspec = mkOption { + type = types.str; + default = "local refspec in the local repository to get the expected reference and avoid stale info"; + }; - timer = mkOption { - type = types.str; - description = "Calendar format everytime we need to run the sync"; - }; - }; - })); + timer = mkOption { + type = types.str; + description = "Calendar format everytime we need to run the sync"; + }; + }; + } + ) + ); description = "Set of branches mapping from cl.forkos.org to other Git repositories"; }; diff --git a/services/gerrit/www.nix b/services/gerrit/www.nix index 83cdcb0..e38ef4c 100644 --- a/services/gerrit/www.nix +++ b/services/gerrit/www.nix @@ -3,39 +3,42 @@ let inherit (lib) mkIf; cfg = config.bagel.services.gerrit; in - { - config = mkIf cfg.enable { - services.nginx = { - enable = true; - enableReload = true; - appendHttpConfig = '' - add_header Permissions-Policy "interest-cohort=()"; - ''; - recommendedProxySettings = false; - }; - services.nginx.virtualHosts.gerrit = { - serverName = builtins.head cfg.domains; - serverAliases = builtins.tail cfg.domains; - enableACME = true; - forceSSL = true; - extraConfig = '' - location / { - proxy_pass http://localhost:4778; - proxy_set_header X-Forwarded-For $remote_addr; - # The :443 suffix is a workaround for https://b.tvl.fyi/issues/88. - proxy_set_header Host $host:443; - # Gerrit can throw a lot of data. - proxy_buffering off; - # NGINX should not give up super fast. Things can take time. - proxy_read_timeout 3600; - } - - location = /robots.txt { - return 200 'User-agent: *\nAllow: /'; - } - ''; - }; - - networking.firewall.allowedTCPPorts = [ 443 80 ]; +{ + config = mkIf cfg.enable { + services.nginx = { + enable = true; + enableReload = true; + appendHttpConfig = '' + add_header Permissions-Policy "interest-cohort=()"; + ''; + recommendedProxySettings = false; }; + services.nginx.virtualHosts.gerrit = { + serverName = builtins.head cfg.domains; + serverAliases = builtins.tail cfg.domains; + enableACME = true; + forceSSL = true; + extraConfig = '' + location / { + proxy_pass http://localhost:4778; + proxy_set_header X-Forwarded-For $remote_addr; + # The :443 suffix is a workaround for https://b.tvl.fyi/issues/88. + proxy_set_header Host $host:443; + # Gerrit can throw a lot of data. + proxy_buffering off; + # NGINX should not give up super fast. Things can take time. + proxy_read_timeout 3600; + } + + location = /robots.txt { + return 200 'User-agent: *\nAllow: /'; + } + ''; + }; + + networking.firewall.allowedTCPPorts = [ + 443 + 80 + ]; + }; } diff --git a/services/hydra/default.nix b/services/hydra/default.nix index 608fb2c..8a131e5 100644 --- a/services/hydra/default.nix +++ b/services/hydra/default.nix @@ -1,4 +1,10 @@ -{ nodes, config, lib, pkgs, ... }: +{ + nodes, + config, + lib, + pkgs, + ... +}: let cfg = config.bagel.services.hydra; @@ -7,46 +13,66 @@ let narCacheDir = "/var/cache/hydra/nar-cache"; port = 3000; - mkCacheSettings = settings: builtins.concatStringsSep "&" ( - lib.mapAttrsToList (k: v: "${k}=${v}") settings - ); + mkCacheSettings = + settings: builtins.concatStringsSep "&" (lib.mapAttrsToList (k: v: "${k}=${v}") settings); # XXX: to support Nix's dumb public host key syntax (base64'd), this outputs # a string with shell-style command interpolations: $(...). - mkBaremetalBuilder = { - parallelBuilds, - publicHostKey, - host, - speedFactor ? 1, - user ? "builder", - supportedSystems ? [ "i686-linux" "x86_64-linux" ], - supportedFeatures ? [ "big-parallel" "kvm" "nixos-test" ], - requiredFeatures ? [ ] - }: - let - supportedFeatures_ = if (supportedFeatures != []) then lib.concatStringsSep "," supportedFeatures else "-"; - requiredFeatures_ = if (requiredFeatures != []) then lib.concatStringsSep "," requiredFeatures else "-"; - in - "ssh://${user}@${host}?remote-store=/mnt ${lib.concatStringsSep "," supportedSystems} ${config.age.secrets.hydra-ssh-key-priv.path} ${toString parallelBuilds} ${toString speedFactor} ${supportedFeatures_} ${requiredFeatures_} $(echo -n '${publicHostKey}' | base64 -w0)"; + mkBaremetalBuilder = + { + parallelBuilds, + publicHostKey, + host, + speedFactor ? 1, + user ? "builder", + supportedSystems ? [ + "i686-linux" + "x86_64-linux" + ], + supportedFeatures ? [ + "big-parallel" + "kvm" + "nixos-test" + ], + requiredFeatures ? [ ], + }: + let + supportedFeatures_ = + if (supportedFeatures != [ ]) then lib.concatStringsSep "," supportedFeatures else "-"; + requiredFeatures_ = + if (requiredFeatures != [ ]) then lib.concatStringsSep "," requiredFeatures else "-"; + in + "ssh://${user}@${host}?remote-store=/mnt ${lib.concatStringsSep "," supportedSystems} ${config.age.secrets.hydra-ssh-key-priv.path} ${toString parallelBuilds} ${toString speedFactor} ${supportedFeatures_} ${requiredFeatures_} $(echo -n '${publicHostKey}' | base64 -w0)"; # TODO: # - generalize to new architectures # - generalize to new features - baremetalBuilders = lib.concatStringsSep "\n" - (map (n: let - assignments = (import ../baremetal-builder/assignments.nix).${n} or { - inherit (nodes.${n}.config.nix.settings) max-jobs; - supported-features = [ "big-parallel" "kvm" "nixos-test" ]; - required-features = []; - }; - in mkBaremetalBuilder { - parallelBuilds = assignments.max-jobs; - supportedFeatures = assignments.supported-features; - requiredFeatures = assignments.required-features; - publicHostKey = ssh-keys.machines.${n}; - host = nodes.${n}.config.networking.fqdn; - }) cfg.builders); -in { + baremetalBuilders = lib.concatStringsSep "\n" ( + map ( + n: + let + assignments = + (import ../baremetal-builder/assignments.nix).${n} or { + inherit (nodes.${n}.config.nix.settings) max-jobs; + supported-features = [ + "big-parallel" + "kvm" + "nixos-test" + ]; + required-features = [ ]; + }; + in + mkBaremetalBuilder { + parallelBuilds = assignments.max-jobs; + supportedFeatures = assignments.supported-features; + requiredFeatures = assignments.required-features; + publicHostKey = ssh-keys.machines.${n}; + host = nodes.${n}.config.networking.fqdn; + } + ) cfg.builders + ); +in +{ options.bagel.services.hydra = with lib; { enable = mkEnableOption "Hydra coordinator"; @@ -58,7 +84,10 @@ in { builders = mkOption { type = types.listOf types.str; description = "List of builders to configure for Hydra"; - example = [ "builder-0" "builder-1" ]; + example = [ + "builder-0" + "builder-1" + ]; }; }; @@ -83,7 +112,12 @@ in { # XXX: Otherwise services.hydra-dev overwrites it to only hydra-queue-runner... # # Can be removed once this is added to some common config template. - nix.settings.trusted-users = [ "root" "hydra" "hydra-www" "@wheel" ]; + nix.settings.trusted-users = [ + "root" + "hydra" + "hydra-www" + "@wheel" + ]; # Because Hydra can't fetch flake inputs otherwise... also yes, this # prefix-based matching is absurdly bad. @@ -111,7 +145,7 @@ in { package = pkgs.hydra; buildMachinesFiles = [ - (pkgs.runCommandNoCC "hydra-builders.conf" {} '' + (pkgs.runCommandNoCC "hydra-builders.conf" { } '' cat >$out <