141 lines
4.2 KiB
Nix
141 lines
4.2 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
cfg = config.homelab.gitops;
|
|
|
|
updateScript = pkgs.writeShellApplication {
|
|
name = "homelab-gitops-update";
|
|
runtimeInputs = [ pkgs.git pkgs.nixos-rebuild pkgs.jq pkgs.coreutils ];
|
|
text = ''
|
|
set -euo pipefail
|
|
|
|
REMOTE_URL="${cfg.repoUrl}"
|
|
BRANCH="${cfg.branch}"
|
|
|
|
echo "Checking remote hash for $REMOTE_URL branch $BRANCH..."
|
|
|
|
# Fetch remote hash, fallback to unknown if it fails
|
|
REMOTE_HASH=$(git ls-remote "$REMOTE_URL" "refs/heads/$BRANCH" | awk '{print $1}' || true)
|
|
|
|
if [ -z "$REMOTE_HASH" ]; then
|
|
echo "WARNING: Could not fetch remote hash. Forcing rebuild to be safe."
|
|
REMOTE_HASH="unknown_remote"
|
|
fi
|
|
|
|
LOCAL_HASH="unknown_local"
|
|
if [ -f /run/current-system/configurationRevision ]; then
|
|
LOCAL_HASH=$(cat /run/current-system/configurationRevision)
|
|
fi
|
|
|
|
echo "Remote hash: $REMOTE_HASH"
|
|
echo "Local hash: $LOCAL_HASH"
|
|
|
|
if [ "$REMOTE_HASH" = "$LOCAL_HASH" ] && [ "$REMOTE_HASH" != "unknown_remote" ] && [ "$LOCAL_HASH" != "unknown" ]; then
|
|
echo "Hashes match. No update needed."
|
|
exit 0
|
|
fi
|
|
|
|
echo "Hashes differ or unknown. Triggering nixos-rebuild..."
|
|
|
|
# Trigger the build and switch
|
|
nixos-rebuild switch --flake "git+$REMOTE_URL?dir=nixos&ref=$BRANCH"
|
|
|
|
echo "Update successful."
|
|
'';
|
|
};
|
|
|
|
in {
|
|
options.homelab.gitops = {
|
|
enable = lib.mkEnableOption "Custom GitOps native deployment system";
|
|
|
|
repoUrl = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "https://git.depeuter.dev/Bos55/nix-config.git";
|
|
description = "The repository URL to pull configurations from.";
|
|
};
|
|
|
|
branch = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "v2";
|
|
description = "The branch to deploy.";
|
|
};
|
|
|
|
useBuilder = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Whether to use the central Builder host to compile packages.";
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
# 1. Systemd Service and Timer for polling
|
|
systemd.services.homelab-gitops = {
|
|
description = "Homelab GitOps Update Service";
|
|
wants = [ "network-online.target" ];
|
|
after = [ "network-online.target" ];
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
ExecStart = "${updateScript}/bin/homelab-gitops-update";
|
|
# Must run as root to rebuild the system
|
|
User = "root";
|
|
};
|
|
};
|
|
|
|
systemd.timers.homelab-gitops = {
|
|
description = "Timer for Homelab GitOps Update Service";
|
|
wantedBy = [ "timers.target" ];
|
|
timerConfig = {
|
|
OnBootSec = "5m";
|
|
OnUnitActiveSec = "5m";
|
|
RandomizedDelaySec = "30s";
|
|
};
|
|
};
|
|
|
|
# 2. Webhook listener for instant trigger
|
|
sops.secrets."webhook-secret" = {};
|
|
|
|
services.webhook = {
|
|
enable = true;
|
|
port = 9000;
|
|
hooks = {
|
|
gitops = {
|
|
execute-command = "${pkgs.systemd}/bin/systemctl";
|
|
pass-arguments-to-command = [
|
|
{ source = "string"; name = "start"; }
|
|
{ source = "string"; name = "homelab-gitops.service"; }
|
|
];
|
|
trigger-rule = {
|
|
match = {
|
|
type = "payload-hash-sha256";
|
|
secret = "{{ getenv \"WEBHOOK_SECRET\" }}";
|
|
parameter = {
|
|
source = "header";
|
|
name = "X-Forgejo-Signature";
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
# Inject the secret as an environment variable into the webhook service
|
|
systemd.services.webhook.serviceConfig.EnvironmentFile = config.sops.secrets."webhook-secret".path;
|
|
|
|
# 3. Builder Configuration
|
|
sops.secrets."builder-ssh-key" = lib.mkIf cfg.useBuilder {};
|
|
|
|
nix.buildMachines = lib.mkIf cfg.useBuilder [
|
|
{
|
|
hostName = "builder.depeuter.dev"; # Must be routable from nodes
|
|
system = "x86_64-linux";
|
|
sshUser = "builder";
|
|
sshKey = config.sops.secrets."builder-ssh-key".path;
|
|
maxJobs = 4;
|
|
speedFactor = 2;
|
|
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
|
|
}
|
|
];
|
|
|
|
nix.distributedBuilds = lib.mkIf cfg.useBuilder true;
|
|
};
|
|
}
|