grafana service
This commit is contained in:
@@ -69,6 +69,13 @@
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
grafana = {
|
||||
module = {
|
||||
name = "grafana";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
79
machines/b4l/services/grafana.nix
Normal file
79
machines/b4l/services/grafana.nix
Normal file
@@ -0,0 +1,79 @@
|
||||
{
|
||||
pkgs,
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
serviceName = "${config.networking.hostName}-grafana";
|
||||
gfDomain = "${
|
||||
config.clan.core.vars.generators."${serviceName}".files.subdomain.value
|
||||
}.${config.networking.fqdn}";
|
||||
|
||||
settingsFormatIni = pkgs.formats.ini {
|
||||
listToValue = concatMapStringsSep " " (generators.mkValueStringDefault { });
|
||||
mkKeyValue = generators.mkKeyValueDefault {
|
||||
mkValueString = v: if v == null then "" else generators.mkValueStringDefault { } v;
|
||||
} "=";
|
||||
};
|
||||
configFile = settingsFormatIni.generate "config.ini" config.services.grafana.settings;
|
||||
in
|
||||
{
|
||||
clan.core.vars.generators."${serviceName}" = {
|
||||
files = {
|
||||
adminpassword.secret = true;
|
||||
subdomain.secret = false;
|
||||
};
|
||||
prompts = {
|
||||
subdomain = {
|
||||
persist = true;
|
||||
type = "line";
|
||||
description = "Sub-domain for Grafana. Default:(grafana)";
|
||||
};
|
||||
adminpassword = {
|
||||
persist = true;
|
||||
type = "hidden";
|
||||
description = "Password for the admin user. Leave empty to auto-generate.";
|
||||
};
|
||||
};
|
||||
|
||||
runtimeInputs = [
|
||||
pkgs.xkcdpass
|
||||
pkgs.coreutils
|
||||
];
|
||||
|
||||
script = ''
|
||||
prompt_domain=$(cat "$prompts"/subdomain)
|
||||
if [[ -n "''${prompt_domain-}" ]]; then
|
||||
echo $prompt_domain | tr -d "\n" > "$out"/subdomain
|
||||
else
|
||||
echo -n "grafana" > "$out"/subdomain
|
||||
fi
|
||||
|
||||
prompt_password=$(cat "$prompts"/adminpassword)
|
||||
if [[ -n "''${prompt_password-}" ]]; then
|
||||
echo "$prompt_password" | tr -d "\n" > "$out"/adminpassword
|
||||
else
|
||||
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminpassword
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
systemd.services.grafana.serviceConfig.ExecStartPre = [
|
||||
"+${pkgs.writeShellScript "grafana-set-password" ''
|
||||
${pkgs.grafana}/bin/grafana cli --homepath ${config.services.grafana.dataDir} --config ${configFile} admin reset-admin-password $(cat ${
|
||||
config.clan.core.vars.generators."${serviceName}".files.adminpassword.path
|
||||
})
|
||||
''}"
|
||||
];
|
||||
|
||||
services.nginx.virtualHosts."${gfDomain}" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "${config.networking.fqdn}";
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${builtins.toString config.services.grafana.settings.server.http_port}";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
24
modules/clan/grafana/default.nix
Normal file
24
modules/clan/grafana/default.nix
Normal file
@@ -0,0 +1,24 @@
|
||||
{ ... }:
|
||||
{
|
||||
_class = "clan.service";
|
||||
manifest.name = "grafana";
|
||||
manifest.description = "Platform for data analytics and monitoring";
|
||||
manifest.categories = [ "System" ];
|
||||
|
||||
roles.default = {
|
||||
|
||||
perInstance.nixosModule =
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
services.grafana = {
|
||||
enable = lib.mkDefault true;
|
||||
};
|
||||
|
||||
clan.core.state.grafana.folders = [ config.services.grafana.dataDir ];
|
||||
};
|
||||
};
|
||||
}
|
18
modules/clan/grafana/flake-module.nix
Normal file
18
modules/clan/grafana/flake-module.nix
Normal file
@@ -0,0 +1,18 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
module = lib.modules.importApply ./default.nix { };
|
||||
in
|
||||
{
|
||||
clan.modules = {
|
||||
grafana = module;
|
||||
};
|
||||
perSystem =
|
||||
{ ... }:
|
||||
{
|
||||
clan.nixosTests.grafana = {
|
||||
imports = [ ./tests/vm/default.nix ];
|
||||
|
||||
clan.modules."@clan/grafana" = module;
|
||||
};
|
||||
};
|
||||
}
|
42
modules/clan/grafana/tests/vm/default.nix
Normal file
42
modules/clan/grafana/tests/vm/default.nix
Normal file
@@ -0,0 +1,42 @@
|
||||
{
|
||||
...
|
||||
}:
|
||||
{
|
||||
name = "service-grafana";
|
||||
|
||||
clan = {
|
||||
directory = ./.;
|
||||
inventory = {
|
||||
machines.server = { };
|
||||
|
||||
instances = {
|
||||
grafana-test = {
|
||||
module.name = "@clan/grafana";
|
||||
module.input = "self";
|
||||
roles.default.machines."server".settings = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nodes = {
|
||||
server = {
|
||||
services.grafana = {
|
||||
settings = {
|
||||
server.domain = "grafana.localhost";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
|
||||
server.wait_for_unit("grafana")
|
||||
|
||||
server.succeed("systemctl status grafana")
|
||||
server.wait_for_open_port(3000)
|
||||
server.succeed("curl -H \"Host: grafana.localhost\" http://127.0.0.1:3000 ")
|
||||
server.succeed("grafana cli -v")
|
||||
'';
|
||||
}
|
1
vars/per-machine/b4l/b4l-grafana/adminpassword/machines/b4l
Symbolic link
1
vars/per-machine/b4l/b4l-grafana/adminpassword/machines/b4l
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../../sops/machines/b4l
|
19
vars/per-machine/b4l/b4l-grafana/adminpassword/secret
Normal file
19
vars/per-machine/b4l/b4l-grafana/adminpassword/secret
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:9v56r2ZaEixMv61TGiCOmeAru2v9ZDUJe6v+Y5TdzfV5Rg==,iv:8kvq06/hfad+9af2PW+50l6Pzs99E5E2x8m3AIz5y90=,tag:aemnUje/OlGc6Hdzzkfdmg==,type:str]",
|
||||
"sops": {
|
||||
"age": [
|
||||
{
|
||||
"recipient": "age1hlzrpqqgndcthq5m5yj9egfgyet2fzrxwa6ynjzwx2r22uy6m3hqr3rd06",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJZUFaNW9GNXZSMnVjTG5v\nKzJlVWxzMnRSbC93a3BHc0t1YVlhQmRGOEZFCkFFK2NQNXJqdWd6cjFxaFRRR2Vy\nZE5tdkcwRXV6ZzVrdGdkcndCQ01KM3MKLS0tIEtDOG5qOG9MWWN4RnZuVGF5ajJN\nMjk0TkJvR3duZHhGTjQ2WVpqRmkrOWsKjPbLas4eDUXdhZyE29AXklDDM+czo2b7\nqvOAY2c+TyMatGpMRMPogUqGC9mj5jTZe+ZfHcxIfytDXbOgldRPow==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
},
|
||||
{
|
||||
"recipient": "age1sg0rvgyetdcqw7j2x983fh69kdkvqsngpe5x36e5920qa7fze3cqhj4wgx",
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtZ3NrbEEyMUpoQTRFL2ZT\nMXNrUTZsSWV3aWRMdGZUNXV2azAwOUJ3cFFRClNmMCtVTXF0VU9PM0NxTWtWSXBh\nMDVlc3BpS3ZVSUlEQit4c21IZy85QW8KLS0tIEMvWWhYM3VyTWk0TnRJbHhublpa\nZEhKSitydFdMbmVWZ01mdlVtSWV6S2sKY7L+wbtpIlo00xQukuj1Fv4iKpC3BftP\n4+55dUhp9cc7VxqV/3TkfPxeyr95OltVZOHhhwSnEzcyCP9XQ16DIw==\n-----END AGE ENCRYPTED FILE-----\n"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2025-08-01T09:25:47Z",
|
||||
"mac": "ENC[AES256_GCM,data:nEaCXu003Y/kwtNrBT+reXOZfTOjhqxUXLvUFa4RFrFREgxIsNkqi80GyDFAaBbgAFA5B71Ozwh8Ml0g3TJ15DsoLkaUgrLR9gXIuh4FoDpFKmvFzUT7nm4Ac003b2bkaMPVNXRU24O+JVgK9U5tmKfqmEkRnlY5MTLFO5EGgnY=,iv:3RpMM6CjtWJSqY8T++2GIV4b3kN724h/ZhuS1U8lJGY=,tag:tkL5+aU06xF4LUeMoq6qoQ==,type:str]",
|
||||
"unencrypted_suffix": "_unencrypted",
|
||||
"version": "3.10.2"
|
||||
}
|
||||
}
|
1
vars/per-machine/b4l/b4l-grafana/adminpassword/users/kurogeek
Symbolic link
1
vars/per-machine/b4l/b4l-grafana/adminpassword/users/kurogeek
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../../sops/users/kurogeek
|
1
vars/per-machine/b4l/b4l-grafana/subdomain/value
Normal file
1
vars/per-machine/b4l/b4l-grafana/subdomain/value
Normal file
@@ -0,0 +1 @@
|
||||
grafana
|
Reference in New Issue
Block a user