mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-11-27 01:13:05 +00:00
Merge pull request #289934 from jnsgruk/scrutiny
This commit is contained in:
commit
78745f4652
@ -85,6 +85,8 @@ The pre-existing [services.ankisyncd](#opt-services.ankisyncd.enable) has been m
|
||||
|
||||
- [RustDesk](https://rustdesk.com), a full-featured open source remote control alternative for self-hosting and security with minimal configuration. Alternative to TeamViewer.
|
||||
|
||||
- [Scrutiny](https://github.com/AnalogJ/scrutiny), a S.M.A.R.T monitoring tool for hard disks with a web frontend.
|
||||
|
||||
- [systemd-lock-handler](https://git.sr.ht/~whynothugo/systemd-lock-handler/), a bridge between logind D-Bus events and systemd targets. Available as [services.systemd-lock-handler.enable](#opt-services.systemd-lock-handler.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-24.05-incompatibilities}
|
||||
|
@ -841,6 +841,7 @@
|
||||
./services/monitoring/riemann.nix
|
||||
./services/monitoring/rustdesk-server.nix
|
||||
./services/monitoring/scollector.nix
|
||||
./services/monitoring/scrutiny.nix
|
||||
./services/monitoring/smartd.nix
|
||||
./services/monitoring/snmpd.nix
|
||||
./services/monitoring/statsd.nix
|
||||
|
221
nixos/modules/services/monitoring/scrutiny.nix
Normal file
221
nixos/modules/services/monitoring/scrutiny.nix
Normal file
@ -0,0 +1,221 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.scrutiny;
|
||||
# Define the settings format used for this program
|
||||
settingsFormat = pkgs.formats.yaml { };
|
||||
in
|
||||
{
|
||||
options = {
|
||||
services.scrutiny = {
|
||||
enable = lib.mkEnableOption "Enables the scrutiny web application.";
|
||||
|
||||
package = lib.mkPackageOptionMD pkgs "scrutiny" { };
|
||||
|
||||
openFirewall = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = "Open the default ports in the firewall for Scrutiny.";
|
||||
};
|
||||
|
||||
influxdb.enable = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = true;
|
||||
description = lib.mdDoc ''
|
||||
Enables InfluxDB on the host system using the `services.influxdb2` NixOS module
|
||||
with default options.
|
||||
|
||||
If you already have InfluxDB configured, or wish to connect to an external InfluxDB
|
||||
instance, disable this option.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
description = lib.mdDoc ''
|
||||
Scrutiny settings to be rendered into the configuration file.
|
||||
|
||||
See https://github.com/AnalogJ/scrutiny/blob/master/example.scrutiny.yaml.
|
||||
'';
|
||||
default = { };
|
||||
type = lib.types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options.web.listen.port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8080;
|
||||
description = lib.mdDoc "Port for web application to listen on.";
|
||||
};
|
||||
|
||||
options.web.listen.host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
description = lib.mdDoc "Interface address for web application to bind to.";
|
||||
};
|
||||
|
||||
options.web.listen.basepath = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "";
|
||||
example = "/scrutiny";
|
||||
description = lib.mdDoc ''
|
||||
If Scrutiny will be behind a path prefixed reverse proxy, you can override this
|
||||
value to serve Scrutiny on a subpath.
|
||||
'';
|
||||
};
|
||||
|
||||
options.log.level = lib.mkOption {
|
||||
type = lib.types.enum [ "INFO" "DEBUG" ];
|
||||
default = "INFO";
|
||||
description = lib.mdDoc "Log level for Scrutiny.";
|
||||
};
|
||||
|
||||
options.web.influxdb.scheme = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "http";
|
||||
description = lib.mdDoc "URL scheme to use when connecting to InfluxDB.";
|
||||
};
|
||||
|
||||
options.web.influxdb.host = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "0.0.0.0";
|
||||
description = lib.mdDoc "IP or hostname of the InfluxDB instance.";
|
||||
};
|
||||
|
||||
options.web.influxdb.port = lib.mkOption {
|
||||
type = lib.types.port;
|
||||
default = 8086;
|
||||
description = lib.mdDoc "The port of the InfluxDB instance.";
|
||||
};
|
||||
|
||||
options.web.influxdb.tls.insecure_skip_verify = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = lib.mdDoc "Skip TLS verification when connecting to InfluxDB.";
|
||||
};
|
||||
|
||||
options.web.influxdb.token = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc "Authentication token for connecting to InfluxDB.";
|
||||
};
|
||||
|
||||
options.web.influxdb.org = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc "InfluxDB organisation under which to store data.";
|
||||
};
|
||||
|
||||
options.web.influxdb.bucket = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc "InfluxDB bucket in which to store data.";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
collector = {
|
||||
enable = lib.mkEnableOption "Enables the scrutiny metrics collector.";
|
||||
|
||||
package = lib.mkPackageOptionMD pkgs "scrutiny-collector" { };
|
||||
|
||||
schedule = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "*:0/15";
|
||||
description = lib.mdDoc ''
|
||||
How often to run the collector in systemd calendar format.
|
||||
'';
|
||||
};
|
||||
|
||||
settings = lib.mkOption {
|
||||
description = lib.mdDoc ''
|
||||
Collector settings to be rendered into the collector configuration file.
|
||||
|
||||
See https://github.com/AnalogJ/scrutiny/blob/master/example.collector.yaml.
|
||||
'';
|
||||
default = { };
|
||||
type = lib.types.submodule {
|
||||
freeformType = settingsFormat.type;
|
||||
|
||||
options.host.id = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
description = lib.mdDoc "Host ID for identifying/labelling groups of disks";
|
||||
};
|
||||
|
||||
options.api.endpoint = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "http://localhost:8080";
|
||||
description = lib.mdDoc "Scrutiny app API endpoint for sending metrics to.";
|
||||
};
|
||||
|
||||
options.log.level = lib.mkOption {
|
||||
type = lib.types.enum [ "INFO" "DEBUG" ];
|
||||
default = "INFO";
|
||||
description = lib.mdDoc "Log level for Scrutiny collector.";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.enable || cfg.collector.enable) {
|
||||
services.influxdb2.enable = cfg.influxdb.enable;
|
||||
|
||||
networking.firewall = lib.mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.settings.web.listen.port ];
|
||||
};
|
||||
|
||||
services.smartd = lib.mkIf cfg.collector.enable {
|
||||
enable = true;
|
||||
extraOptions = [
|
||||
"-A /var/log/smartd/"
|
||||
"--interval=600"
|
||||
];
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services = {
|
||||
scrutiny = lib.mkIf cfg.enable {
|
||||
description = "Hard Drive S.M.A.R.T Monitoring, Historical Trends & Real World Failure Thresholds";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
environment = {
|
||||
SCRUTINY_VERSION = "1";
|
||||
SCRUTINY_WEB_DATABASE_LOCATION = "/var/lib/scrutiny/scrutiny.db";
|
||||
SCRUTINY_WEB_SRC_FRONTEND_PATH = "${cfg.package}/share/scrutiny";
|
||||
};
|
||||
serviceConfig = {
|
||||
DynamicUser = true;
|
||||
ExecStart = "${lib.getExe cfg.package} start --config ${settingsFormat.generate "scrutiny.yaml" cfg.settings}";
|
||||
Restart = "always";
|
||||
StateDirectory = "scrutiny";
|
||||
StateDirectoryMode = "0750";
|
||||
};
|
||||
};
|
||||
|
||||
scrutiny-collector = lib.mkIf cfg.collector.enable {
|
||||
description = "Scrutiny Collector Service";
|
||||
environment = {
|
||||
COLLECTOR_VERSION = "1";
|
||||
COLLECTOR_API_ENDPOINT = cfg.collector.settings.api.endpoint;
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${lib.getExe cfg.collector.package} run --config ${settingsFormat.generate "scrutiny-collector.yaml" cfg.collector.settings}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
timers = lib.mkIf cfg.collector.enable {
|
||||
scrutiny-collector = {
|
||||
timerConfig = {
|
||||
OnCalendar = cfg.collector.schedule;
|
||||
Persistent = true;
|
||||
Unit = "scrutiny-collector.service";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = [ lib.maintainers.jnsgruk ];
|
||||
}
|
@ -772,6 +772,7 @@ in {
|
||||
sanoid = handleTest ./sanoid.nix {};
|
||||
scaphandre = handleTest ./scaphandre.nix {};
|
||||
schleuder = handleTest ./schleuder.nix {};
|
||||
scrutiny = handleTest ./scrutiny.nix {};
|
||||
sddm = handleTest ./sddm.nix {};
|
||||
seafile = handleTest ./seafile.nix {};
|
||||
searx = handleTest ./searx.nix {};
|
||||
|
70
nixos/tests/scrutiny.nix
Normal file
70
nixos/tests/scrutiny.nix
Normal file
@ -0,0 +1,70 @@
|
||||
import ./make-test-python.nix ({ lib, ... }:
|
||||
|
||||
{
|
||||
name = "scrutiny";
|
||||
meta.maintainers = with lib.maintainers; [ jnsgruk ];
|
||||
|
||||
nodes = {
|
||||
machine = { self, pkgs, lib, ... }: {
|
||||
services = {
|
||||
scrutiny.enable = true;
|
||||
scrutiny.collector.enable = true;
|
||||
};
|
||||
|
||||
environment.systemPackages =
|
||||
let
|
||||
seleniumScript = pkgs.writers.writePython3Bin "selenium-script"
|
||||
{
|
||||
libraries = with pkgs.python3Packages; [ selenium ];
|
||||
} ''
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.firefox.options import Options
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
|
||||
options = Options()
|
||||
options.add_argument("--headless")
|
||||
service = webdriver.FirefoxService(executable_path="${lib.getExe pkgs.geckodriver}") # noqa: E501
|
||||
|
||||
driver = webdriver.Firefox(options=options, service=service)
|
||||
driver.implicitly_wait(10)
|
||||
driver.get("http://localhost:8080/web/dashboard")
|
||||
|
||||
wait = WebDriverWait(driver, 10).until(
|
||||
EC.text_to_be_present_in_element(
|
||||
(By.TAG_NAME, "body"), "Drive health at a glance")
|
||||
)
|
||||
|
||||
body_text = driver.find_element(By.TAG_NAME, "body").text
|
||||
assert "Temperature history for each device" in body_text
|
||||
|
||||
driver.close()
|
||||
'';
|
||||
in
|
||||
with pkgs; [ curl firefox-unwrapped geckodriver seleniumScript ];
|
||||
};
|
||||
};
|
||||
# This is the test code that will check if our service is running correctly:
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
# Wait for InfluxDB to be available
|
||||
machine.wait_for_unit("influxdb2")
|
||||
machine.wait_for_open_port(8086)
|
||||
|
||||
# Wait for Scrutiny to be available
|
||||
machine.wait_for_unit("scrutiny")
|
||||
machine.wait_for_open_port(8080)
|
||||
|
||||
# Ensure the API responds as we expect
|
||||
output = machine.succeed("curl localhost:8080/api/health")
|
||||
assert output == '{"success":true}'
|
||||
|
||||
# Start the collector service to send some metrics
|
||||
collect = machine.succeed("systemctl start scrutiny-collector.service")
|
||||
|
||||
# Ensure the application is actually rendered by the Javascript
|
||||
machine.succeed("PYTHONUNBUFFERED=1 selenium-script")
|
||||
'';
|
||||
})
|
53
pkgs/by-name/sc/scrutiny-collector/package.nix
Normal file
53
pkgs/by-name/sc/scrutiny-collector/package.nix
Normal file
@ -0,0 +1,53 @@
|
||||
{ buildGoModule
|
||||
, fetchFromGitHub
|
||||
, makeWrapper
|
||||
, smartmontools
|
||||
, nixosTests
|
||||
, lib
|
||||
}:
|
||||
let
|
||||
version = "0.7.2";
|
||||
in
|
||||
buildGoModule rec {
|
||||
inherit version;
|
||||
pname = "scrutiny-collector";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "AnalogJ";
|
||||
repo = "scrutiny";
|
||||
rev = "refs/tags/v${version}";
|
||||
hash = "sha256-UYKi+WTsasUaE6irzMAHr66k7wXyec8FXc8AWjEk0qs=";
|
||||
};
|
||||
|
||||
subPackages = "collector/cmd/collector-metrics";
|
||||
|
||||
vendorHash = "sha256-SiQw6pq0Fyy8Ia39S/Vgp9Mlfog2drtVn43g+GXiQuI=";
|
||||
|
||||
buildInputs = [ makeWrapper ];
|
||||
|
||||
CGO_ENABLED = 0;
|
||||
|
||||
ldflags = [ "-extldflags=-static" ];
|
||||
|
||||
tags = [ "static" ];
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir -p $out/bin
|
||||
cp $GOPATH/bin/collector-metrics $out/bin/scrutiny-collector-metrics
|
||||
wrapProgram $out/bin/scrutiny-collector-metrics \
|
||||
--prefix PATH : ${lib.makeBinPath [ smartmontools ]}
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
passthru.tests.scrutiny-collector = nixosTests.scrutiny;
|
||||
|
||||
meta = {
|
||||
description = "Hard disk metrics collector for Scrutiny.";
|
||||
homepage = "https://github.com/AnalogJ/scrutiny";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ jnsgruk ];
|
||||
mainProgram = "scrutiny-collector-metrics";
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
}
|
68
pkgs/by-name/sc/scrutiny/package.nix
Normal file
68
pkgs/by-name/sc/scrutiny/package.nix
Normal file
@ -0,0 +1,68 @@
|
||||
{ buildNpmPackage
|
||||
, buildGoModule
|
||||
, fetchFromGitHub
|
||||
, nixosTests
|
||||
, lib
|
||||
}:
|
||||
let
|
||||
pname = "scrutiny";
|
||||
version = "0.7.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "AnalogJ";
|
||||
repo = "scrutiny";
|
||||
rev = "refs/tags/v${version}";
|
||||
hash = "sha256-UYKi+WTsasUaE6irzMAHr66k7wXyec8FXc8AWjEk0qs=";
|
||||
};
|
||||
|
||||
frontend = buildNpmPackage {
|
||||
inherit version;
|
||||
pname = "${pname}-webapp";
|
||||
src = "${src}/webapp/frontend";
|
||||
|
||||
npmDepsHash = "sha256-M8P41LPg7oJ/C9abDuNM5Mn+OO0zK56CKi2BwLxv8oQ=";
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
mkdir dist
|
||||
npm run build:prod --offline -- --output-path=dist
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
mkdir $out
|
||||
cp -r dist/* $out
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
in
|
||||
buildGoModule rec {
|
||||
inherit pname src version;
|
||||
|
||||
subPackages = "webapp/backend/cmd/scrutiny";
|
||||
|
||||
vendorHash = "sha256-SiQw6pq0Fyy8Ia39S/Vgp9Mlfog2drtVn43g+GXiQuI=";
|
||||
|
||||
CGO_ENABLED = 0;
|
||||
|
||||
ldflags = [ "-extldflags=-static" ];
|
||||
|
||||
tags = [ "static" ];
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $out/share/scrutiny
|
||||
cp -r ${frontend}/* $out/share/scrutiny
|
||||
'';
|
||||
|
||||
passthru.tests.scrutiny = nixosTests.scrutiny;
|
||||
|
||||
meta = {
|
||||
description = "Hard Drive S.M.A.R.T Monitoring, Historical Trends & Real World Failure Thresholds.";
|
||||
homepage = "https://github.com/AnalogJ/scrutiny";
|
||||
license = lib.licenses.mit;
|
||||
maintainers = with lib.maintainers; [ jnsgruk ];
|
||||
mainProgram = "scrutiny";
|
||||
platforms = lib.platforms.linux;
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user