This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

configs.monitoring: export the superconfig revision each machine runs

autoUpgrade pins the upgrade to the revision the forward-only guard resolved and writes it to /var/lib/superconfig-revision after a successful upgrade, like deploy does. Vector reads that file every 30s and exports nixos_system_info{host,revision,revision_short}; the node dashboard shows host -> revision_short.

+98 -4
+25 -2
configs/autoupdate.nix
··· 7 7 let 8 8 flake = "github:lassulus/superconfig"; 9 9 10 + # The revision the guard checked; the upgrade is pinned to it, so the 11 + # revision recorded afterwards is the one actually switched to. 12 + revFile = "/run/nixos-upgrade/rev"; 13 + 10 14 # system.autoUpgrade switches to whatever the flake currently evaluates to, 11 15 # forwards or backwards. A machine deployed from an unpushed local checkout 12 16 # therefore gets reverted to the older remote HEAD on the next timer run. ··· 38 42 fi 39 43 remote=$(jq -r '.lastModified // 0' <<<"$meta") 40 44 if [ "$remote" -gt "$deployed" ]; then 45 + jq -r .revision <<<"$meta" >${revFile} 41 46 exit 0 42 47 fi 43 48 echo "autoupgrade: ${flake} is at $remote, running system was deployed at $deployed; skipping" ··· 48 53 { 49 54 system.autoUpgrade = { 50 55 enable = true; 51 - inherit flake; 56 + # Goes into the nixos-upgrade script unquoted, so the shell expands the 57 + # pinned revision. Without a rev file (guard could not reach the flake) 58 + # the ref stays unpinned and the recorded revision becomes unknown. 59 + flake = "${flake}/$(cat ${revFile} 2>/dev/null)"; 52 60 randomizedDelaySec = "6h"; 53 61 }; 54 62 55 - systemd.services.nixos-upgrade.serviceConfig.ExecCondition = lib.getExe guard; 63 + systemd.services.nixos-upgrade.serviceConfig = { 64 + RuntimeDirectory = "nixos-upgrade"; 65 + ExecCondition = lib.getExe guard; 66 + # Only runs after a successful upgrade. Read by the monitoring agent. 67 + ExecStartPost = lib.getExe ( 68 + pkgs.writeShellApplication { 69 + name = "autoupgrade-record-revision"; 70 + runtimeInputs = [ pkgs.coreutils ]; 71 + text = '' 72 + rev=$(cat ${revFile} 2>/dev/null || echo unknown) 73 + echo "$rev" >/var/lib/superconfig-revision.tmp 74 + mv /var/lib/superconfig-revision.tmp /var/lib/superconfig-revision 75 + ''; 76 + } 77 + ); 78 + }; 56 79 }
+54 -2
configs/monitoring/agent.nix
··· 1 1 # Vector on every machine: host metrics and the journal, written to every 2 2 # monitoring server (dual write). Each sink has its own disk buffer, so a 3 3 # server outage or a laptop being offline doesn't lose data. 4 - { config, lib, ... }: 4 + { 5 + config, 6 + lib, 7 + pkgs, 8 + ... 9 + }: 5 10 let 6 11 inherit (import ./default.nix) servers ports; 7 12 ··· 14 19 sinksFor = server: { 15 20 "metrics_${server}" = { 16 21 type = "prometheus_remote_write"; 17 - inputs = [ "host_metrics" ]; 22 + inputs = [ 23 + "host_metrics" 24 + "revision_metric" 25 + ]; 18 26 endpoint = "http://${server}.r:${toString ports.victoriametrics}/api/v1/write"; 19 27 healthcheck.enabled = false; 20 28 inherit buffer; ··· 67 75 scrape_interval_secs = 30; 68 76 }; 69 77 sources.journald_raw.type = "journald"; 78 + 79 + # The superconfig revision the machine runs, written by deploy and 80 + # autoUpgrade after a switch. Read at runtime: it is in no derivation, 81 + # so a new commit doesn't change every machine's closure. 82 + sources.revision_raw = { 83 + type = "exec"; 84 + mode = "scheduled"; 85 + scheduled.exec_interval_secs = 30; 86 + command = [ 87 + pkgs.runtimeShell 88 + "-c" 89 + "cat /var/lib/superconfig-revision 2>/dev/null || echo unknown" 90 + ]; 91 + include_stderr = false; 92 + }; 93 + transforms.revision = { 94 + type = "remap"; 95 + inputs = [ "revision_raw" ]; 96 + source = '' 97 + rev = strip_whitespace(string!(.message)) 98 + if rev == "" { rev = "unknown" } 99 + . = { 100 + "value": 1, 101 + "revision": rev, 102 + "revision_short": replace(rev, r'^([0-9a-f]{7})[0-9a-f]{33}', "$1"), 103 + } 104 + ''; 105 + }; 106 + transforms.revision_metric = { 107 + type = "log_to_metric"; 108 + inputs = [ "revision" ]; 109 + metrics = [ 110 + { 111 + type = "gauge"; 112 + field = "value"; 113 + name = "nixos_system_info"; 114 + tags = { 115 + host = config.networking.hostName; 116 + revision = "{{revision}}"; 117 + revision_short = "{{revision_short}}"; 118 + }; 119 + } 120 + ]; 121 + }; 70 122 71 123 # The NixOS hostname as host label on every metric, the same value the 72 124 # journal events get below (alerts and dashboards match on it).
+19
configs/monitoring/dashboards/node.json
··· 129 129 "legendFormat": "{{host}} write" 130 130 } 131 131 ] 132 + }, 133 + { 134 + "id": 7, 135 + "type": "table", 136 + "title": "superconfig revision", 137 + "gridPos": { "x": 0, "y": 24, "w": 12, "h": 8 }, 138 + "datasource": { "type": "victoriametrics-metrics-datasource", "uid": "victoriametrics" }, 139 + "options": { "sortBy": [{ "displayName": "host", "desc": false }] }, 140 + "targets": [ 141 + { 142 + "refId": "A", 143 + "expr": "max by (host, revision_short) (nixos_system_info{host=~\"$host\"})", 144 + "format": "table", 145 + "instant": true 146 + } 147 + ], 148 + "transformations": [ 149 + { "id": "organize", "options": { "excludeByName": { "Time": true, "Value": true } } } 150 + ] 132 151 } 133 152 ] 134 153 }