From 76e09ce5c38d721f293a375964ff7c8638b365f5 Mon Sep 17 00:00:00 2001 From: yukkop Date: Fri, 3 Oct 2025 19:02:33 +0000 Subject: [PATCH] =?UTF-8?q?fix(package):=20`sentin=C3=A8lla`:=20base64=20l?= =?UTF-8?q?ogic?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nixos/module/hectic/service/sentinèlla.nix | 6 ++-- package/sentinèlla/default.nix | 33 ++++++++++++++++------ package/sentinèlla/probe-loop.sh | 31 ++++++++++++++------ package/sentinèlla/probe.sh | 7 +++-- 4 files changed, 53 insertions(+), 24 deletions(-) diff --git a/nixos/module/hectic/service/sentinèlla.nix b/nixos/module/hectic/service/sentinèlla.nix index ee3e387..8107023 100644 --- a/nixos/module/hectic/service/sentinèlla.nix +++ b/nixos/module/hectic/service/sentinèlla.nix @@ -10,7 +10,7 @@ ... }: let system = pkgs.system; - cfg = config.hectic.services.server-health; + cfg = config.hectic.services."sentinèlla"; # URLS="http://..." # default: none # VOLUMES="/ /home" # default: all from df -P in { @@ -67,15 +67,13 @@ in { }; config = lib.mkMerge [ (lib.mkIf cfg.probe.enable { - services.nginx.virtualHosts = { - }; systemd.services."sentinèlla-probe" = { description = "Hectic server health check"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; - ExecStart = "${self.packages.${system}.server-health}/bin/probe"; + ExecStart = "${self.packages.${system}."sentinèlla"}/bin/probe"; EnvironmentFile = cfg.probe.environmentPath; Environment = (if cfg.probe.urls != null then [ "URLS=${cfg.probe.urls}" diff --git a/package/sentinèlla/default.nix b/package/sentinèlla/default.nix index c1efaaa..2fd7b3a 100644 --- a/package/sentinèlla/default.nix +++ b/package/sentinèlla/default.nix @@ -1,10 +1,25 @@ -{ writeShellScriptBin, socat, dash }: -writeShellScriptBin "server-health" '' - set +a - LOOP_FILE=${./probe-loop.sh} - socat() { ${socat}/bin/socat $@ } - dash() { ${dash}/bin/dash $@ } - set -a +{ symlinkJoin, writeShellApplication, socat, dash, hectic, curl }: +let + # TODO: writeDashApplication + probe = writeShellApplication { + name = "probe"; + runtimeInputs = [ socat dash probe-loop ]; + text = builtins.readFile ./probe.sh; + }; - ${dash}/bin/dash ${./probe.sh} -'' + probe-loop = writeShellApplication { + name = "probe-loop"; + runtimeInputs = [ ]; + text = builtins.readFile ./probe-loop.sh; + }; + + sentinel = writeShellApplication { + name = "sentinel"; + runtimeInputs = [ hectic.shellplot curl ]; + text = builtins.readFile ./sentinel.sh; + }; +in +symlinkJoin { + name = "sentinèlla"; + paths = [ probe sentinel ]; +} diff --git a/package/sentinèlla/probe-loop.sh b/package/sentinèlla/probe-loop.sh index 7e25f9f..cbb6a7f 100644 --- a/package/sentinèlla/probe-loop.sh +++ b/package/sentinèlla/probe-loop.sh @@ -1,4 +1,4 @@ -#!/bin/dash +#!/usr/bin/env dash # router.sh — POSIX sh HTTP backend (for socat) # usage: socat -T5 -t5 TCP-LISTEN:${port},reuseaddr,fork EXEC:"sh ${currentfile}" @@ -6,9 +6,10 @@ # GET /status -> check $URLS (0/0 if unset) # GET /disk -> check $VOLUMES (all if unset) # Env: -# URLS="http://..." # default: none -# VOLUMES="/ /home" # default: all from df -P +# URLS="http://..." # default: none +# VOLUMES="/ /home" # default: all from df -P # TIMEOUT=5 +# AUTH_FILE="/path/htpasswd-like" # lines: user:pass base64() { local mod @@ -55,9 +56,10 @@ base64() { b=buildbin($1) l=length(b) lack = (6 - l % 6) % 6 - b = sprintf("%s%0*d", b, lack, 0) + for(i=1;i<=lack;i+=1) { + b = sprintf("%s0", b) + } r = base64(b) - print lack for(i=1;i<=lack/2;i+=1) { r = sprintf("%s=", r) } @@ -135,8 +137,16 @@ route_disk() { } } +AUTH_TOKENS="" +if [ -n "$AUTH_FILE" ] && [ -r "$AUTH_FILE" ]; then + while IFS= read -r up || [ -n "$up" ]; do + [ -n "$up" ] || continue + AUTH_TOKENS="$AUTH_TOKENS $(base64 encode "$up" | tail -n1)" + done <"$AUTH_FILE" +fi + require_auth=false -[ -n "$USER" ] && [ -n "$PASS" ] && require_auth=true +[ -n "$AUTH_TOKENS" ] && require_auth=true # --- read request & headers --- IFS= read -r req || exit 0 @@ -166,9 +176,12 @@ unauth() { printf '%s' "$body" } -if $require_auth && ! $auth_ok; then - unauth - exit 0 +auth_ok=false +if $require_auth; then + for t in $AUTH_TOKENS; do + [ "$tok" = "$t" ] && auth_ok=true && break + done + $auth_ok || { unauth; exit 0; } fi tmp=$(mktemp) || exit 1 diff --git a/package/sentinèlla/probe.sh b/package/sentinèlla/probe.sh index fdaae2d..4d4addc 100644 --- a/package/sentinèlla/probe.sh +++ b/package/sentinèlla/probe.sh @@ -1,3 +1,6 @@ -#!/bin/dash +#!/usr/bin/env dash +set -euo pipefail +socat -V >/dev/null +dash -c 'echo ok' >/dev/null -socat -T5 -t5 TCP-LISTEN:"${PORT:-5988}",reuseaddr,fork EXEC:"dash $LOOP_FILE" +socat -T5 -t5 TCP-LISTEN:"${PORT:-5988}",reuseaddr,fork EXEC:"dash ${LOOP_FILE:-probe-loop}"