157 lines
6.0 KiB
Nix
157 lines
6.0 KiB
Nix
{
|
|
config,
|
|
pkgs,
|
|
inputs,
|
|
service_configs,
|
|
lib,
|
|
...
|
|
}:
|
|
let
|
|
jellyfinExporterPort = service_configs.ports.private.jellyfin_exporter.port;
|
|
qbitExporterPort = service_configs.ports.private.qbittorrent_exporter.port;
|
|
igpuExporterPort = service_configs.ports.private.igpu_exporter.port;
|
|
minecraftExporterPort = service_configs.ports.private.minecraft_exporter.port;
|
|
minecraftServerName = service_configs.minecraft.server_name;
|
|
minecraftServerPort = service_configs.ports.public.minecraft.port;
|
|
in
|
|
{
|
|
# -- Jellyfin Prometheus Exporter --
|
|
# Replaces custom jellyfin-collector.nix textfile timer.
|
|
# Exposes per-session metrics (jellyfin_now_playing_state) and library stats.
|
|
systemd.services.jellyfin-exporter =
|
|
lib.mkIf (config.services.grafana.enable && config.services.jellyfin.enable)
|
|
{
|
|
description = "Prometheus exporter for Jellyfin";
|
|
after = [
|
|
"network.target"
|
|
"jellyfin.service"
|
|
];
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig = {
|
|
ExecStart = lib.getExe (
|
|
pkgs.writeShellApplication {
|
|
name = "jellyfin-exporter-wrapper";
|
|
runtimeInputs = [ pkgs.jellyfin-exporter ];
|
|
text = ''
|
|
exec jellyfin_exporter \
|
|
--jellyfin.address=http://127.0.0.1:${toString service_configs.ports.private.jellyfin.port} \
|
|
--jellyfin.token="$(cat "$CREDENTIALS_DIRECTORY/jellyfin-api-key")" \
|
|
--web.listen-address=127.0.0.1:${toString jellyfinExporterPort}
|
|
'';
|
|
}
|
|
);
|
|
Restart = "on-failure";
|
|
RestartSec = "10s";
|
|
DynamicUser = true;
|
|
NoNewPrivileges = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
MemoryDenyWriteExecute = true;
|
|
LoadCredential = "jellyfin-api-key:${config.age.secrets.jellyfin-api-key.path}";
|
|
};
|
|
};
|
|
|
|
# -- qBittorrent Prometheus Exporter --
|
|
# Replaces custom qbittorrent-collector.nix textfile timer.
|
|
# Exposes per-torrent metrics (qbit_dlspeed, qbit_upspeed) and aggregate stats.
|
|
# qBittorrent runs in a VPN namespace; the exporter reaches it via namespace address.
|
|
systemd.services.qbittorrent-exporter =
|
|
lib.mkIf (config.services.grafana.enable && config.services.qbittorrent.enable)
|
|
{
|
|
description = "Prometheus exporter for qBittorrent";
|
|
after = [
|
|
"network.target"
|
|
"qbittorrent.service"
|
|
];
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig = {
|
|
ExecStart =
|
|
lib.getExe' inputs.qbittorrent-metrics-exporter.packages.${pkgs.system}.default
|
|
"qbittorrent-metrics-exporter";
|
|
Restart = "on-failure";
|
|
RestartSec = "10s";
|
|
DynamicUser = true;
|
|
NoNewPrivileges = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
};
|
|
environment = {
|
|
HOST = "127.0.0.1";
|
|
PORT = toString qbitExporterPort;
|
|
SCRAPE_INTERVAL = "15";
|
|
BACKEND = "in-memory";
|
|
# qBittorrent has AuthSubnetWhitelist=0.0.0.0/0, so no real password needed.
|
|
# The exporter still expects the env var to be set.
|
|
QBITTORRENT_PASSWORD = "unused";
|
|
QBITTORRENT_USERNAME = "admin";
|
|
TORRENT_HOSTS = "qbit:main=http://${config.vpnNamespaces.wg.namespaceAddress}:${toString config.services.qbittorrent.webuiPort}|http://${config.vpnNamespaces.wg.namespaceAddress}:${toString config.services.qbittorrent.webuiPort}";
|
|
RUST_LOG = "warn";
|
|
};
|
|
};
|
|
|
|
# -- Intel GPU Prometheus Exporter --
|
|
# Replaces custom intel-gpu-collector.nix + intel-gpu-collector.py textfile timer.
|
|
# Exposes engine busy%, frequency, and RC6 metrics via /metrics.
|
|
# Requires privileged access to GPU debug interfaces (intel_gpu_top).
|
|
systemd.services.igpu-exporter = lib.mkIf config.services.grafana.enable {
|
|
description = "Prometheus exporter for Intel integrated GPU";
|
|
wantedBy = [ "multi-user.target" ];
|
|
path = [ pkgs.intel-gpu-tools ];
|
|
serviceConfig = {
|
|
ExecStart = lib.getExe pkgs.igpu-exporter;
|
|
Restart = "on-failure";
|
|
RestartSec = "10s";
|
|
# intel_gpu_top requires root-level access to GPU debug interfaces
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
};
|
|
environment = {
|
|
PORT = toString igpuExporterPort;
|
|
REFRESH_PERIOD_MS = "30000";
|
|
};
|
|
};
|
|
|
|
# -- Minecraft Prometheus Exporter --
|
|
# itzg/mc-monitor queries the local server via SLP on each scrape and exposes
|
|
# minecraft_status_{healthy,response_time_seconds,players_online_count,players_max_count}.
|
|
# mc-monitor binds to 0.0.0.0 (no listen-address flag); the firewall keeps
|
|
# 9567 internal and IPAddressAllow pins the socket to loopback as defense-in-depth.
|
|
systemd.services.minecraft-exporter =
|
|
lib.mkIf (config.services.grafana.enable && config.services.minecraft-servers.enable)
|
|
{
|
|
description = "Prometheus exporter for Minecraft (mc-monitor SLP)";
|
|
after = [
|
|
"network.target"
|
|
"minecraft-server-${minecraftServerName}.service"
|
|
];
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig = {
|
|
ExecStart = "${lib.getExe pkgs.mc-monitor} export-for-prometheus";
|
|
Restart = "on-failure";
|
|
RestartSec = "10s";
|
|
DynamicUser = true;
|
|
NoNewPrivileges = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
MemoryDenyWriteExecute = true;
|
|
RestrictAddressFamilies = [
|
|
"AF_INET"
|
|
"AF_INET6"
|
|
];
|
|
IPAddressAllow = [
|
|
"127.0.0.0/8"
|
|
"::1/128"
|
|
];
|
|
IPAddressDeny = "any";
|
|
};
|
|
environment = {
|
|
EXPORT_SERVERS = "127.0.0.1:${toString minecraftServerPort}";
|
|
EXPORT_PORT = toString minecraftExporterPort;
|
|
TIMEOUT = "5s";
|
|
};
|
|
};
|
|
}
|