fix: litellm -> grafana

This commit is contained in:
2026-07-13 10:32:34 +02:00
parent 8d57aa4bc0
commit d58173760d
8 changed files with 849 additions and 95 deletions
+104 -5
View File
@@ -1,20 +1,97 @@
{config, ...}: let
{
config,
pkgs,
...
}: let
serviceName = "litellm";
servicePort = config.m3ta.ports.get serviceName;
prmNetbirdIP = "100.91.49.26";
cldNetbirdIP = "100.91.203.184";
python = pkgs.python3.withPackages (ps: [ps.pyyaml]);
litellmConfigGenerator = pkgs.writeText "litellm-config-generator.py" ''
import sys
from pathlib import Path
import yaml
base_path = Path(sys.argv[1])
target_path = Path(sys.argv[2])
with base_path.open("r", encoding="utf-8") as fh:
config = yaml.safe_load(fh) or {}
settings = config.get("litellm_settings")
if not isinstance(settings, dict):
settings = {}
config["litellm_settings"] = settings
def ensure_list(value):
if value is None:
return []
if isinstance(value, list):
return value
return [value]
callbacks = ensure_list(settings.get("callbacks"))
if "prometheus" not in callbacks:
callbacks.append("prometheus")
settings["callbacks"] = callbacks
service_callbacks = ensure_list(settings.get("service_callback"))
if "prometheus_system" not in service_callbacks:
service_callbacks.append("prometheus_system")
settings["service_callback"] = service_callbacks
# LiteLLM >= 1.85 protects /metrics by default. Keep auth enabled;
# Prometheus scrapes with a bearer token from an agenix secret on AZ-PRM-1.
settings["require_auth_for_metrics_endpoint"] = True
target_path.parent.mkdir(parents=True, exist_ok=True)
with target_path.open("w", encoding="utf-8") as fh:
yaml.safe_dump(config, fh, sort_keys=False)
'';
in {
systemd.services."podman-${serviceName}".preStart = ''
set -euo pipefail
base_config="/var/lib/${serviceName}/config.yaml"
target_config="/run/${serviceName}/config.yaml"
multiproc_dir="/var/lib/${serviceName}/prometheus-multiproc"
if [ ! -f "$base_config" ]; then
echo "Missing LiteLLM base config: $base_config" >&2
exit 1
fi
mkdir -p "$(dirname "$target_config")" "$multiproc_dir"
rm -f "$multiproc_dir"/*
chmod 0777 "$multiproc_dir"
${python}/bin/python ${litellmConfigGenerator} "$base_config" "$target_config"
chmod 0644 "$target_config"
'';
virtualisation.oci-containers.containers.${serviceName} = {
#image = "ghcr.io/berriai/litellm:v1.78.5-stable";
image = "docker.litellm.ai/berriai/litellm:1.89.0";
ports = ["127.0.0.1:${toString servicePort}:4000"];
image = "docker.litellm.ai/berriai/litellm:1.92.0";
ports = [
"127.0.0.1:${toString servicePort}:4000"
"${cldNetbirdIP}:${toString servicePort}:4000"
];
cmd = ["--config" "/app/config.yaml" "--port" "4000"];
environmentFiles = [config.age.secrets.litellm-env.path];
environment = {
ANONYMIZED_TELEMETRY = "False";
DO_NOT_TRACK = "True";
SCARF_NO_ANALYTICS = "True";
STORE_MODEL_IN_DB = "True";
LITELLM_LOG = "json";
PROMETHEUS_MULTIPROC_DIR = "/prometheus_multiproc";
};
volumes = ["/var/lib/litellm/config.yaml:/app/config.yaml"];
volumes = [
"/run/${serviceName}/config.yaml:/app/config.yaml:ro"
"/var/lib/${serviceName}/prometheus-multiproc:/prometheus_multiproc"
];
extraOptions = ["--add-host=postgres:10.89.0.1" "--ip=10.89.0.30" "--network=web"];
};
@@ -26,6 +103,23 @@ in {
}
];
middlewares."${serviceName}-metrics-local-only".ipAllowList.sourceRange = [
"127.0.0.1/32"
"::1/128"
"${prmNetbirdIP}/32"
];
routers."${serviceName}-metrics" = {
rule = "Host(`llm.az-gruppe.com`) && PathPrefix(`/metrics`)";
tls = {
certResolver = "ionos";
};
service = serviceName;
entrypoints = "websecure";
middlewares = ["${serviceName}-metrics-local-only"];
priority = 200;
};
routers.${serviceName} = {
rule = "Host(`llm.az-gruppe.com`)";
tls = {
@@ -33,6 +127,11 @@ in {
};
service = serviceName;
entrypoints = "websecure";
priority = 1;
};
};
networking.firewall.extraCommands = ''
iptables -A INPUT -p tcp -s ${prmNetbirdIP} --dport ${toString servicePort} -j ACCEPT
'';
}