From a1719b8529808e874453df2dabdca9367f22212d Mon Sep 17 00:00:00 2001 From: emily Date: Thu, 16 May 2024 17:07:39 +0200 Subject: [PATCH] added update-nixfiles --- .sops.yaml | 6 ++ config/hosts/seras/configuration.nix | 3 +- config/services/update-nixfiles.nix | 11 ++++ modules/default.nix | 1 + modules/update-nixfiles/default.nix | 72 +++++++++++++++++++++ pkgs/overlay.nix | 1 + pkgs/update-nixfiles/default.nix | 2 + pkgs/update-nixfiles/update-nixfiles.sh | 83 ++++++++++++++++++++++--- secrets/services/update-nixfiles.yaml | 34 ++++++++++ 9 files changed, 205 insertions(+), 8 deletions(-) create mode 100644 config/services/update-nixfiles.nix create mode 100644 modules/update-nixfiles/default.nix create mode 100644 secrets/services/update-nixfiles.yaml diff --git a/.sops.yaml b/.sops.yaml index 279058b..6a70ab5 100644 --- a/.sops.yaml +++ b/.sops.yaml @@ -33,3 +33,9 @@ creation_rules: - *emily age: - *seras + - path_regex: secrets/services/update-nixfiles.yaml + key_groups: + - pgp: + - *emily + age: + - *seras diff --git a/config/hosts/seras/configuration.nix b/config/hosts/seras/configuration.nix index 9dbad99..423281f 100644 --- a/config/hosts/seras/configuration.nix +++ b/config/hosts/seras/configuration.nix @@ -1,4 +1,4 @@ -{ config, inputs, lib, pkgs, ... }: { +{ ... }: { imports = [ ../../common ../../profiles/builder.nix @@ -7,6 +7,7 @@ ../../profiles/lxc.nix ../../services/nginx.nix ../../services/hydra + ../../services/update-nixfiles.nix ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; diff --git a/config/services/update-nixfiles.nix b/config/services/update-nixfiles.nix new file mode 100644 index 0000000..2268adc --- /dev/null +++ b/config/services/update-nixfiles.nix @@ -0,0 +1,11 @@ +{ config, ... }:{ + sops.secrets."services/update-nixfiles/privateKey" = { + owner = "update-nixfiles"; + sopsFile = ../../secrets/services/update-nixfiles.yaml; + }; + kyouma.update-nixfiles = { + enable = true; + privateKey = config.sops.secrets."services/update-nixfiles/privateKey".path; + signingKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINeGC9ezGSZFXokVfQ6ETnn94xLwi1VVhWol2WEjQI35 update-nixfiles@seras"; + }; +} diff --git a/modules/default.nix b/modules/default.nix index 3577ffb..9f59827 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -3,5 +3,6 @@ ./deployment ./machine-type ./nginx + ./update-nixfiles ]; } diff --git a/modules/update-nixfiles/default.nix b/modules/update-nixfiles/default.nix new file mode 100644 index 0000000..34b6e7e --- /dev/null +++ b/modules/update-nixfiles/default.nix @@ -0,0 +1,72 @@ +{ config, lib, pkgs, ... }: +with lib; +let cfg = config.kyouma.update-nixfiles; +in { + options.kyouma.update-nixfiles = { + enable = mkEnableOption "automatically update nixfiles inputs"; + privateKey = mkOption { + type = types.str; + default = ""; + description = "Private key path"; + }; + signingKey = mkOption { + type = types.str; + default = ""; + description = "Public Key"; + }; + runFreq = mkOption { + type = types.str; + default = "*-*-* 04:20:00"; + description = "How often nixfiles should be updated. See {manpage}`systemd.timer(5)`"; + }; + }; + config = mkIf cfg.enable { + users.groups.update-nixfiles = {}; + users.users.update-nixfiles = { + group = "update-nixfiles"; + isSystemUser = true; + useDefaultShell = true; + }; + home-manager.users.update-nixfiles = { + home.stateVersion = "23.11"; + programs.git = { + enable = true; + signing.key = builtins.toFile "signingKey" cfg.signingKey; + signing.signByDefault = true; + userName = "Update Bot"; + userEmail = "update-nixfiles-bot@kyouma.net"; + extraConfig = { + gpg.format = "ssh"; + }; + }; + programs.ssh = { + addKeysToAgent = "yes"; + matchBlocks."git.bsd.gay".indentityFile = cfg.privateKey; + }; + services.ssh-agent.enable = true; + }; + programs.ssh = { + knownHosts."git.bsd.gay".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHd48YPVXBWVdQwVAF16Ihs7FNTPmD1kMUnOfQttc1bA"; + }; + systemd.services.update-nixfiles = { + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + restartIfChanged = false; + unitConfig.X-StopOnRemoval = false; + + serviceConfig = { + ExecStart = "${pkgs.update-nixfiles}/bin/update-nixfiles"; + User = "update-nixfiles"; + }; + }; + systemd.timers.update-nixfiles = { + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = cfg.runFreq; + }; + requires = [ "network-online.target" ]; + after = [ "network-online.target" ]; + }; + environment.systemPackages = [ pkgs.update-nixfiles ]; + }; +} diff --git a/pkgs/overlay.nix b/pkgs/overlay.nix index ff2e0a5..1b6be83 100644 --- a/pkgs/overlay.nix +++ b/pkgs/overlay.nix @@ -1,4 +1,5 @@ final: prev: { nyastodon = final.callPackage ./nyastodon/default.nix { }; upgrade-system = final.callPackage ./upgrade-system/default.nix { }; + update-nixfiles = final.callPackage ./update-nixfiles/default.nix { }; } diff --git a/pkgs/update-nixfiles/default.nix b/pkgs/update-nixfiles/default.nix index 4c4355c..4880da0 100644 --- a/pkgs/update-nixfiles/default.nix +++ b/pkgs/update-nixfiles/default.nix @@ -8,5 +8,7 @@ pkgs.writeShellApplication { jq nix gnugrep + git + openssh ]; } diff --git a/pkgs/update-nixfiles/update-nixfiles.sh b/pkgs/update-nixfiles/update-nixfiles.sh index 7bc64a5..fff20d9 100644 --- a/pkgs/update-nixfiles/update-nixfiles.sh +++ b/pkgs/update-nixfiles/update-nixfiles.sh @@ -2,25 +2,94 @@ set -euo pipefail -BRANCH="update-inputs" +BRANCH="update-inputs-$(date +%Y-%m-%d-%H-%M)" HYDRA_URL="https://hydra.kyouma.net" JOBSET_URL="${HYDRA_URL}/jobset/nixfiles/update-inputs" ROOT="$(mktemp -d)" +gitin () { + git -C "${ROOT}" "$@" +} + +merge_theirs () { + gitin merge -s ours "${BRANCH}" -m "Update from ${BRANCH}" + gitin branch temp + gitin reset --hard "${BRANCH}" + gitin reset --soft temp + gitin commit --amend --no-edit + gitin branch -D temp +} + test_build () { local build_jobs build_jobs="$(curl --fail -s -L -H "Accept: application/json" "${JOBSET_URL}/latest-eval" | jq -r ".builds | .[]")" for build in ${build_jobs}; do - local build_url - build_status="$(curl -s -L -H "Accept: application/json" "https://hydra.kyouma.net/build/${build}" | jq -r ".buildstatus")" - [[ $build_status != 0 ]] && exit 1 + local build_status + while true; do + local build_finished + build_finished="$(curl --fail -s -L -H "Accept: application/json" "${HYDRA_URL}/build/${build}" | jq -r ".finished")" + [[ ${build_finished} == 1 ]] && break + sleep 5 + done + build_status="$(curl --fail -s -L -H "Accept: application/json" "${HYDRA_URL}/build/${build}" | jq -r ".buildstatus")" + [[ $build_status != 0 ]] && echo "Build ${build} failed" && exit 1 + echo "Build ${build} was successful" done } -git clone git@git.bsd.gay:snaki/nixfiles.git +wait_for_hydra () { + local git_rev + local hydra_rev + local counter + counter=0 + git_rev="$(gitin rev-parse update-inputs)" + while [[ $counter -le 30 ]]; do + hydra_rev="$(curl -s -L -H "Accept: application/json" "${JOBSET_URL}/latest-eval" 2> /dev/null | jq -r .flake | sed -E "s/.+&rev=(.*)/\1/g")" + if [[ "${git_rev}" == "${hydra_rev}" ]]; then + echo "Hydra got new commit" + break + fi + sleep 30 + ((counter++)) + done + if [[ $counter -ge 30 ]]; then + echo "Hydra no workey" + exit 1 + fi +} -git checkout -b "${BRANCH}" +git clone git@git.bsd.gay:snaki/nixfiles.git "${ROOT}" +gitin fetch --all +gitin checkout origin/main +gitin checkout -b "${BRANCH}" + +pushd "${ROOT}" nix flake update --commit-lock-file +popd -git push --set-upstream origin "${BRANCH}" +if gitin diff --quiet origin/update-inputs "${BRANCH}"; then + echo "No update needed" + gitin checkout update-inputs + gitin branch -D "${BRANCH}" + exit 0 +fi + +gitin push --set-upstream origin "${BRANCH}" + +gitin checkout update-inputs +merge_theirs +gitin push origin update-inputs + +echo "Waiting for hydra to get new commit" +wait_for_hydra + +echo "Testing if all build jobs completed successfully" +test_build +echo "All build jobs were successful" + +echo "Merging ${BRANCH} into main" +gitin checkout main +gitin merge --ff-only "${BRANCH}" +gitin push origin main +echo "Update successful" diff --git a/secrets/services/update-nixfiles.yaml b/secrets/services/update-nixfiles.yaml new file mode 100644 index 0000000..2ccb6a4 --- /dev/null +++ b/secrets/services/update-nixfiles.yaml @@ -0,0 +1,34 @@ +services: + update-nixfiles: + privateKey: ENC[AES256_GCM,data:FxjLHx90OrWB8GZ2nTh78Lx9vxBggQze46uqj/bSluknENAE2Tm0E37IWtloE3cBXVrU+nu/kKp56ReNhGYa+JkZsW4FLYlPYol8trwxRx1/X3+GrGNf/YiEioCtl1S27IYtSKtn05ymqgmFRuk9h4kC6tRNYhfukXf3HK8GCEJkH15sGmM87JkxH+eGYiL645I5DJxs2OEW6zXCuwo9JBhRmi5HXoRAmY65R5wpoXlXiUj39rBGwpCmAB68ktijBAbi0oP7OUa+0FnzgnYgUgUZyaYlzWWi4xIGbymBeqcg4MNgwEITzO8xhvjfugjYFI6DJfz2JQn3MVGPzhfpTg+Lo1PSR6e+Vwr6AHoSFI/vcabt4bqVaPCeC0Vz6RKItAbGqacq9wsQyhmkwy8Eeca3yVYdIrciNP8Z9/F2zY/I4UOv+4AMWAMnbtZq3PXVLTPsCVVSS89pQfEToj+WT7DImNYFVMXneRH4RCos3GiUiJVTpM7InhHIFScWwJ8uLHeNBgsd77KBDF0YIWO8,iv:cpRa4W+T7eGhSqrvMc8p4CPnI2Jgt51VWTSp+jALGFk=,tag:eXFnO8HBclWrrjRFAGBs2Q==,type:str] +sops: + kms: [] + gcp_kms: [] + azure_kv: [] + hc_vault: [] + age: + - recipient: age1ht2wetcyl9rzu45e02pqqwgmyfsfe6y6ygxyuxpfhnkdm62d3pqsg3uqvd + enc: | + -----BEGIN AGE ENCRYPTED FILE----- + YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6amNhV1VLenczMFFOZnBx + ODczY2gxY3ZWQmxnb2N0WWtua3JLemhOMVZvCi9VV1gxVlViYXI4b0Y5a2JacGNr + WDJJb1FRamRpSkE0dXg1TWlQNWFvcmsKLS0tIGJKY1dtUTNacHhYaVJ0R25TaVJn + eVVsTkxzR1RveVM1V3Fxb0hUVk50am8KYeZtl4YHQemreYSEeKWMFNKsquPUbO1X + O/0NJ7zekDvkWrhq17gJ0VYXKBnSU03rrvPx2ebAzZKkSv0CHbA5IQ== + -----END AGE ENCRYPTED FILE----- + lastmodified: "2024-05-16T14:46:36Z" + mac: ENC[AES256_GCM,data:lqZ/W3TiMKlHt/DO4aJcjIZG+bz2Y2c7BANC03LVs1DhVHKryaA+TZuV9ub0Og2cfieMzJbcmo6e/m4RHkc22fRDWU825uHeMW4zB0dHJ0SnLTxyB42D5b8PWncS/zSIqF/pbzLTSl3VwlWo4Sk06DC24ynyxsTJjMGF3Y4J0oc=,iv:x8tzQKsotPWcbR3D5+Cov1u89k4tovQFz4mxjcsMzKM=,tag:GSow3VJGo4tp0aE7zgd29w==,type:str] + pgp: + - created_at: "2024-05-16T14:44:40Z" + enc: |- + -----BEGIN PGP MESSAGE----- + + hF4D1GtNSlou/HkSAQdAka1CA7opApVGScjzdXIJboeJHWUAsxX9UM2nEylD8DQw + YZ8ZQtUcorN/jBCOrOMTGfIXbKKum+iDDdhg6ufue5D+JayjDsTeWiXStnFVkkTA + 0l4BQdaGG+6WKNRYW1oqnkxh9FqOWpFQUsRI8LxE6EbBpcxGRgdKxNj9Bs9IlyaB + dqMSe1J44htiz+bx/B8Sv4L/ygtSf+YhCCqopFI83UgTpT1BWxmg8wGfA9k/s2Wt + =Xnzw + -----END PGP MESSAGE----- + fp: B04F01A7A98A13020C39B4A68AB7B773A214ACE5 + unencrypted_suffix: _unencrypted + version: 3.8.1