diff options
-rw-r--r-- | flake.lock | 23 | ||||
-rw-r--r-- | flake.nix | 6 | ||||
-rw-r--r-- | hosts/ahmed/linus.onl/default.nix | 79 | ||||
-rw-r--r-- | secrets/linus.onl-github-secret.txt.age | bin | 0 -> 1061 bytes | |||
-rw-r--r-- | secrets/secrets.nix | 1 |
5 files changed, 97 insertions, 12 deletions
@@ -223,7 +223,8 @@ "nix-darwin": "nix-darwin", "nixpkgs": "nixpkgs", "nixpkgs-unstable": "nixpkgs-unstable", - "push-notification-api": "push-notification-api" + "push-notification-api": "push-notification-api", + "webhook-listener": "webhook-listener" } }, "systems": { @@ -255,6 +256,26 @@ "repo": "default", "type": "github" } + }, + "webhook-listener": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1727892481, + "narHash": "sha256-fgsNGC8VaoH9LcSMHwMufuFUZpH6oq4pVQVnmp2Q0Mo=", + "owner": "linnnus", + "repo": "webhook-listener", + "rev": "c0ff85fd243f0e6cb3f5d4d0d61ad33cc893108f", + "type": "github" + }, + "original": { + "owner": "linnnus", + "repo": "webhook-listener", + "type": "github" + } } }, "root": "root", @@ -27,6 +27,10 @@ url = "github:linnnus/comma-zsh"; inputs.nixpkgs.follows = "nixpkgs"; }; + webhook-listener = { + url = "github:linnnus/webhook-listener"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { @@ -36,6 +40,7 @@ nix-darwin, agenix, push-notification-api, + webhook-listener, ... } @ inputs: let args = { @@ -82,6 +87,7 @@ home-manager.nixosModules.home-manager agenix.nixosModules.default push-notification-api.nixosModules.default + webhook-listener.nixosModules.default ./hosts/ahmed/configuration.nix ./hosts/common.nix ./home diff --git a/hosts/ahmed/linus.onl/default.nix b/hosts/ahmed/linus.onl/default.nix index 3c4f7a6..f176228 100644 --- a/hosts/ahmed/linus.onl/default.nix +++ b/hosts/ahmed/linus.onl/default.nix @@ -1,6 +1,7 @@ { pkgs, lib, + config, ... }: let # The domain to serve. Also kinda embedded in the name of the module?? @@ -8,6 +9,12 @@ # Enable HTTPS stuff. useACME = true; + + # When run, this command causes a rebuild of the website source. See the service defintion for how the site is rebuilt. + startServiceCommand = "/run/current-system/sw/bin/systemctl start ${domain}-source.service"; + + # Name of the "production" branch where the live content goes. + mainBranch = "main"; in { config = { # Create a user to run the build script under. @@ -26,7 +33,7 @@ in { chmod 0755 /var/www/${domain} ''; - # Create a systemd service which rebuild the site regularly. + # Create a systemd service which rebuild the site. # # This can't be done using Nix because the site relies on the git build and # there are some inherent difficulties with including .git/ in the @@ -34,8 +41,6 @@ in { # # See: https://github.com/NixOS/nix/issues/6900 # See: https://github.com/NixOS/nixpkgs/issues/8567 - # - # TODO: Integrate rebuilding with GitHub webhooks to rebuild on push. systemd.services."${domain}-source" = { description = "generate https://${domain} source"; @@ -58,8 +63,7 @@ in { tmpdir="$(mktemp -d -t linus.onl-source.XXXXXXXXXXXX)" cd "$tmpdir" trap 'rm -rf $tmpdir' EXIT - # TODO: Only do minimal possible cloning - git clone https://github.com/linnnus/${domain} . + git clone --depth=1 --branch=${mainBranch} https://github.com/linnnus/${domain} . make _build rsync --archive --delete _build/ /var/www/${domain} ''; @@ -76,14 +80,60 @@ in { wantedBy = ["nginx.service"]; }; - # Start the source fetching shit only after network acess has been achieved. - systemd.timers."${domain}-source" = { - after = ["network-online.target"]; - requires = ["network-online.target"]; - wantedBy = ["timers.target"]; - timerConfig.OnCalendar = ["*-*-* *:00/5:00"]; + # This service will listen for webhook events from GitHub's API. Whenever + # it receives a "push" event, it will start the rebuild service. + services.webhook-listener = { + enable = true; + + commands = [ + { + event = "push"; + command = toString (pkgs.writeShellScript "handle-push-event.sh" '' + ${pkgs.jq}/bin/jq --exit-status '.ref == "refs/heads/${mainBranch}"' >/dev/null + case $? in + 0) + ${config.security.wrapperDir}/sudo ${startServiceCommand} + ;; + 1) + echo "Not the target ref. Exciting" + exit 0 + ;; + *) + echo "Got jq error. Exiting." >&2 + exit 1 + ;; + esac + ''); + } + ]; + + max-idle-time = "10min"; + + secret-path = config.age.secrets."linus.onl-github-secret".path; }; + # We have shared a secret with GitHub, which we use to verify requests. Here we decrypt that secret. + age.secrets."linus.onl-github-secret" = { + file = ../../../secrets/linus.onl-github-secret.txt.age; + + owner = config.services.webhook-listener.user; + group = config.services.webhook-listener.group; + }; + + # Commands run by `webhook-listener` are run as an inpriviledged user for + # security reasons. We have to specifically give that user permission to start this one service. + security.sudo.extraRules = [ + { + users = [config.services.webhook-listener.user]; + commands = [ + { + command = startServiceCommand; + options = ["NOPASSWD"]; + } + ]; + } + ]; + # Register domain name with ddns. services.cloudflare-dyndns.domains = [domain]; @@ -94,6 +144,13 @@ in { enableACME = useACME; forceSSL = useACME; root = "/var/www/${domain}"; + + # I have pointed the GitHub webhook requests at <https://linus.onl/webhook>. + # These should be forwarded to `/` on the listening socket server. + locations."= /webhook" = { + recommendedProxySettings = true; + proxyPass = "http://unix:${config.services.webhook-listener.socket-path}:/"; + }; }; }; }; diff --git a/secrets/linus.onl-github-secret.txt.age b/secrets/linus.onl-github-secret.txt.age Binary files differnew file mode 100644 index 0000000..e90a6d5 --- /dev/null +++ b/secrets/linus.onl-github-secret.txt.age diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 308adad..a747bcb 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -9,4 +9,5 @@ in { "duksebot.env.age".publicKeys = [muhammedKey ahmedKey]; "mullvad-wg.key.age".publicKeys = [muhammedKey ahmedKey]; "wraaath-sftp-password.txt.age".publicKeys = [muhammedKey ahmedKey]; + "linus.onl-github-secret.txt.age".publicKeys = [muhammedKey ahmedKey]; } |