diff --git a/hosts/server/configuration.nix b/hosts/server/configuration.nix index 429e6e5..db8a4d2 100644 --- a/hosts/server/configuration.nix +++ b/hosts/server/configuration.nix @@ -28,6 +28,7 @@ ../../server-modules/umami.nix ../../server-modules/gitea.nix ../../server-modules/mealie.nix + ../../server-modules/auto-upgrade.nix # You should let those lines as is ./hardware-configuration.nix diff --git a/hosts/server/secrets/default.nix b/hosts/server/secrets/default.nix index a571e26..3187d92 100644 --- a/hosts/server/secrets/default.nix +++ b/hosts/server/secrets/default.nix @@ -23,6 +23,8 @@ path = "/home/hadi/.ssh/key.pub"; mode = "0600"; }; + signal-sender-number = {}; + signal-receiver-number = {}; }; }; diff --git a/hosts/server/secrets/secrets.yaml b/hosts/server/secrets/secrets.yaml index 6206863..f385d88 100644 --- a/hosts/server/secrets/secrets.yaml +++ b/hosts/server/secrets/secrets.yaml @@ -1,5 +1,7 @@ umami-secret: ENC[AES256_GCM,data:tImpd4sD92Omf/YFB8YE4gxAu+g801wQNR+k5rhY6AbzIIYOzpVmQL4XGjfp9Teky3olii4s3XTcmTyuMoxMWg==,iv:QFAEzYnAnxOOtrHWiM2IkvSs0Aqk3s1T5X7j5WC+tO8=,tag:FIbgHLfRVMJ2qZ6dOJ8zLw==,type:str] sshconfig: ENC[AES256_GCM,data:R54HVxqAyj9yGO/AYL8p6cnXgYxkQKW9XveHlBMTnDXBJ7r/4HgnefdymprnXmdlbNWcWrRqmaLEuzJs/0BfixXfMvmGTUrmJ0ASVuDrz9k6rOLADAKFikQh0dib7NU4JmPgmUzMncXc2WuCd3BCG3kwBQ==,iv:Ro9FA+MzTAp+ERQMT88z8ioCox/dTj2vWcqCDOSLag4=,tag:5XiXIyz5/pjGFOB5ZjdOVg==,type:str] +signal-sender-number: ENC[AES256_GCM,data:y5zTe2HgBlPLDzTi,iv:Bx3aoo3BbfdeeJxDcvMYHOAzBTKTKakz5OsLlqIBU9w=,tag:aFGYO8g+gvDtb5X5w1QnLg==,type:str] +signal-receiver-number: ENC[AES256_GCM,data:WV/yxRGAFNA0HWbT,iv:Y7xL3MEe21H7Ly4FTIbkmNLHZTq5mpR+WS6vDqfP2P4=,tag:doRQ2/qenOHSBwqC6lWoDg==,type:str] github-key: ENC[AES256_GCM,data:NRYhcBIwGJEV13+YECLR+2IErsn/7clbnkx0Mltr7dQajSb5WHZ3QDH0KQPylEHhplE5IVS0h4I0z+Pb1B0UteCxFmJ5wZq+2BKZkvE7G3dojqBpgHcVqJV2GLEJkRjlHfRgsbq/OBe8xcsPh20P1KUyP0WIwVbpt+9dFWGxEGYkp2uSyuBIJ98kElt0zuVgl7WcYoDO7v5WmGzZfla+yZwURvMk8zcM3gopo+4KL6YnYUs+UA3VlBBn6VK4Nvbqy6X0R0+ZA5HHAXg+OFgGmfWnENZmsyQJHXEchGGgEldzThkQ4r8yMkgN/ax+AGouLyzbITapGE4sE11FFgL6Hmp4pSXxl3UAGF+cvV5pIujbb28CXmSPRMyYpoNxI93PSYz/txAzE6Cr2dgwxR4zpMelv4i6IaGnY8NgpY8jp2Y6C0uuJxJCN0RtnjQw1rM2uRnm7vMGyU7XXz9DEVfGnYpTWnykXsEjHE5DVGy80ejYQlc6dtmf3vdTWpt+YYdCPw8/cd0PIx2D6geh1c28,iv:wl+RG24mXYMklD8CBGXVD36DMhlWT/7zh8ZMvr7vgOk=,tag:OJhqF8PoXotr7IsyFW6q1g==,type:str] adguard-pwd: ENC[AES256_GCM,data:CAmZFpKN6FFRlCk=,iv:cz45T/z2ZYHNC46FNVp2YHmdhXD4ERhM31+Jo+9PkSk=,tag:GTUvzkYSP4flXs/HUNGYhw==,type:str] recyclarr: ENC[AES256_GCM,data:eJNbGHb4SZvbF7FAHMrpRynmpVyPiTpyZqNx40Fo+lanqdm7d7oRhkLD2PfqxpTcIyV6BxJk12wGUC0uWVuAihmToL/Ih2FJWIQFUOdbaov/xNWHE9mtoRX/A3gIwD8e3DoFMK/dAk2/TyvvAfxi2eYTDJvxecEttHQGxafq1jveHFDcC9e1aFk3M8O8YlX5yF3zl90mugsUVP+iaSURnY/nglZuEDzfJ6Edge7r5OSL6WYh3OUIu1yzuuKXRZ47B/gpXO/cP89JMmxdPj3FUJkk7Htf0s9ALzpVE9fRohDGcpPIkR6COCLTL+mqvVmyopA1zPoX8/X8eiuocpaT3vqJit7Bc6InzflY/5rlg1x0SyoXWQfEsperfNBeiZGngp382I7rrZ8QSwF4AIsmngNeyDRAnfasAU5OVwK+yPIVhRueEFLNrJPG3j2hpArlzpvY2EPBVJDrYwFslis8CASoUdvu6C7VxtJXFcOZR8QemwJarJFU7v1bVhQoIkarn3V7FfAXg/8RfYrn9HAIq5AiFFbQRNHWXzIceIgNKQFb5yfagtMtMq6XKhjsV07jeYt9X/YU80XRfkPm05yiLdLQHcDNmlB3R+SFPD7qjTE7LuSH1Kdc3DvxwrKfHJLsJ+nSIL1po8gDMW8BPc0g4n4dpQ6CFK5BaDFK4eovNpgAXoRC9orkGw/16YmMozp6J78VJLzu3jcYMFbySFznDUuWcFf/7dVV+7pLAj2ffWXzScLISRBhZ9RNUMaZAKAk7WTmxBhw0yzNiih8OFUkbpp1FFLuU0bnBY0iEz+8/OSwv8H7t0HYe29HO61p1huH34B/ZkPA5VLKivFh2mOPNzbvMqtIAkq1ro82Psvc6t88gVIc+VAOZ9zDLohp0FXrNVXwnrs7fxevQa0pUClDivO1ib5G4Znor7q+13jZglmh3G7nHiniO607dRoxszzVEQdTn8ku3XAfIPStsSfQwH46nXhr2kDkspcA7BqwJph0dsKKlfzf22C0OJkDY0L1DgKFvJRmmKAhOdB6XxXYwS+BcDT+8ugejTKpulyPSsbdb0m9p9lVAVu0GMxFEbUsuE+QHiAAP5Vle7swpl4h3i8uHSfKFra3qEswwRnPAHhPSdLSaSU6O6T5gN/b0hhO6dAiNR0UOkOG59fPasL0MRpeb3SkM4Nd6g5b/hY8dXaXR7pQHvh+4GmfJFWYaWm/cZ8k9JAYAw9Sn/spWnjRmpv9bnSxADGbkdV8NDHquDDDFVIIoDnWhQJpqrL61KZITx2Ete1SYdNiy++p3mOYisJgHDsRR1RNQNxhRW4EY8c5nCzgc8x+rU432pCOfMbAuGEfQXMwMGFGeoUg6EL5xEyUEJ/aqymxI+Vjk8h7KfDnOyyL/+1BKEd/GccrjeQfeZGRLI0Tu5gVgL6twc+u4av6inNMMhPFzZuVrfeo6bip5C8R0dK6Pbdz2L/fsgn3E4NNi14NM/DgLLhJRLvKQdCQx+BT+3soNRw5htTzuNS48MD2YDwZYvNfu6mo0r4j4I7Tj8zuCjddbGVa2/5XnhcfdUBx1VOd90H1RKkk8kgSoR0bgo7mLls=,iv:HT3a2YnFy0cF9qUO671kwqxuzFfNnfqynCUVGHf+3dM=,tag:nrA++7fsnc4Cx0OPSDKaRw==,type:str] @@ -18,7 +20,7 @@ sops: TEc5d01RaVFGNXc3dlljM0FTTHpENjQKOqwI+pl8UxVIVl43glnOYvW660/PsDGY yefODJGVtHrOm3yeXC2xlTi3sFW+c5wUl2yPqddbvcBt5Ud/yd4iXQ== -----END AGE ENCRYPTED FILE----- - lastmodified: "2026-04-11T00:11:27Z" - mac: ENC[AES256_GCM,data:r9TA1kBOZzn5fZP9Yj6UFhtd7kfoyou0PBDeudBIi3DCBuvFkCpYmsDCQVjheYfeZT3TIpUdqTNi2WsS9ck7IXcZtr4FCrhxcLzWMFvZetnMyAET5OakzrfuaQ496xEavYLQOkPJH5ueCcTUVq7L2PhJVg8xnC61c52xgzva+wQ=,iv:4MgiU9wXOrMtdA7qvWTSLLNpcDUeiBd5GVR381iuyqM=,tag:IOwPh+6rAL6sTUMBOJChjw==,type:str] + lastmodified: "2026-04-12T17:00:46Z" + mac: ENC[AES256_GCM,data:D1XabvMWdpFF1g5F8RpPmu/QxFPFPBcrldFMJb4qaA3L3nGGGcb3Gke90dCl4i1bQFl5dG84VTjPWX2NsP6HDH8aa2aNYqXN7J049HTnC34xgyhfBNTDmR+eawKIYGSUkhcnxnxWqtt2O+2kwJgzDPKI9k6vBnIHw2wzt2cUw/4=,iv:UJwJesdFcN3ITtndFF7jWl48+sJJcG82pM4ydeToy5M=,tag:Kkhy/Lle6bJ7w7Ijz0sN5Q==,type:str] unencrypted_suffix: _unencrypted version: 3.12.2 diff --git a/server-modules/auto-upgrade.nix b/server-modules/auto-upgrade.nix new file mode 100644 index 0000000..5a750c4 --- /dev/null +++ b/server-modules/auto-upgrade.nix @@ -0,0 +1,77 @@ +# Auto upgrade some of my inputs every hour. +# With signal notification on failure, but only once per failure streak to avoid spamming me if something is broken for a while. +{ + config, + pkgs, + ... +}: let + configDir = config.var.configDirectory; + auto-update-inputs = ["blog" "awesome-wallpapers" "iknowyou" "default-creds"]; + signalConfigDir = "/var/lib/signal-cli"; + sentinelFile = "/var/lib/nixos-auto-upgrade/failure-notified"; +in { + sops.secrets."signal-sender-number" = {}; + sops.secrets."signal-receiver-number" = {}; + + environment.systemPackages = [pkgs.signal-cli]; + + systemd.tmpfiles.rules = [ + "d /var/lib/nixos-auto-upgrade 0700 root root -" + "d ${signalConfigDir} 0700 root root -" + ]; + + # Main upgrade service + systemd.services.nixos-auto-upgrade = { + description = "NixOS auto upgrade"; + after = ["network-online.target"]; + wants = ["network-online.target"]; + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + onFailure = ["nixos-auto-upgrade-notify.service"]; + script = '' + set -e + cd ${configDir} + ${pkgs.nix}/bin/nix flake update ${builtins.concatStringsSep " " auto-update-inputs} + /run/current-system/sw/bin/nixos-rebuild switch --flake ${configDir}#jack + # Clear failure sentinel on success + rm -f ${sentinelFile} + ''; + }; + + # Notification service — only fires once per failure streak + systemd.services.nixos-auto-upgrade-notify = { + description = "Signal notification on NixOS upgrade failure"; + serviceConfig = { + Type = "oneshot"; + User = "root"; + }; + script = '' + # Already notified for this failure streak, skip + if [ -f "${sentinelFile}" ]; then + exit 0 + fi + + SENDER=$(cat ${config.sops.secrets."signal-sender-number".path}) + RECEIVER=$(cat ${config.sops.secrets."signal-receiver-number".path}) + ${pkgs.signal-cli}/bin/signal-cli \ + --config ${signalConfigDir} \ + -u "$SENDER" send \ + -m "Jack: nixos-auto-upgrade failed, check the logs: journalctl -u nixos-auto-upgrade" \ + "$RECEIVER" + + touch ${sentinelFile} + ''; + }; + + # Hourly timer + systemd.timers.nixos-auto-upgrade = { + description = "NixOS auto upgrade timer"; + wantedBy = ["timers.target"]; + timerConfig = { + OnCalendar = "hourly"; + Persistent = true; + }; + }; +}