2022-03-16 09:49:54 -07:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
hostname = config.instance.hostname;
|
|
|
|
domain-name = config.fudo.hosts.${hostname}.domain;
|
|
|
|
domain = config.fudo.domains.${domain-name};
|
|
|
|
|
2023-10-14 16:15:26 -07:00
|
|
|
host-fqdn = hostname:
|
|
|
|
let host-domain = config.fudo.hosts.${hostname}.domain;
|
|
|
|
in "${hostname}.${host-domain}";
|
2022-03-16 09:49:54 -07:00
|
|
|
|
|
|
|
logAggregationEnabled = domain.log-aggregator != null;
|
|
|
|
isLogAggregator = hostname == domain.log-aggregator;
|
|
|
|
|
2023-10-14 16:15:26 -07:00
|
|
|
is-private-network = let site-name = config.fudo.hosts.${hostname}.site;
|
2022-03-16 09:49:54 -07:00
|
|
|
in config.fudo.sites.${site-name}.local-gateway != null;
|
|
|
|
|
|
|
|
cfg = config.fudo.services.logging;
|
|
|
|
|
|
|
|
in {
|
|
|
|
options.fudo.services.logging = with types; {
|
|
|
|
loki = {
|
|
|
|
port = mkOption {
|
|
|
|
type = port;
|
|
|
|
description = "Port on which to listen on localhost.";
|
|
|
|
default = 3021;
|
|
|
|
};
|
|
|
|
|
|
|
|
state-directory = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "Path at which to store state for Loki.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
promtail = {
|
|
|
|
http-listen-port = mkOption {
|
|
|
|
type = port;
|
|
|
|
default = 6041;
|
|
|
|
};
|
|
|
|
grpc-listen-port = mkOption {
|
|
|
|
type = port;
|
|
|
|
default = 6042;
|
|
|
|
};
|
|
|
|
user = mkOption {
|
|
|
|
type = str;
|
|
|
|
description = "User as which to run promtail job.";
|
|
|
|
default = "promtail";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf logAggregationEnabled {
|
|
|
|
users = {
|
|
|
|
users.${cfg.promtail.user} = {
|
|
|
|
isSystemUser = true;
|
|
|
|
uid = 441;
|
|
|
|
group = cfg.promtail.user;
|
|
|
|
};
|
|
|
|
groups = {
|
|
|
|
${cfg.promtail.user}.members = [ cfg.promtail.user ];
|
2023-10-14 16:15:26 -07:00
|
|
|
systemd-journal = { members = [ cfg.promtail.user ]; };
|
2022-03-16 09:49:54 -07:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
fudo = let
|
|
|
|
aggregator-domain = config.fudo.hosts.${domain.log-aggregator}.domain;
|
|
|
|
log-aggregator-fqdn = "${domain.log-aggregator}.${aggregator-domain}";
|
|
|
|
in {
|
|
|
|
zones.${domain.zone} = {
|
|
|
|
aliases.log-aggregator = "${log-aggregator-fqdn}.";
|
|
|
|
};
|
|
|
|
|
2023-10-14 16:15:26 -07:00
|
|
|
metrics.grafana.datasources =
|
|
|
|
let scheme = if is-private-network then "http" else "https";
|
|
|
|
in {
|
|
|
|
"loki-${domain.log-aggregator}" = {
|
|
|
|
url = "${scheme}://log-aggregator.${aggregator-domain}";
|
|
|
|
type = "loki";
|
|
|
|
};
|
2022-03-16 09:49:54 -07:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
services = {
|
|
|
|
nginx = mkIf isLogAggregator {
|
|
|
|
enable = true;
|
|
|
|
|
|
|
|
virtualHosts."log-aggregator.${domain-name}" = {
|
2023-10-14 16:15:26 -07:00
|
|
|
enableACME = !is-private-network;
|
|
|
|
forceSSL = !is-private-network;
|
2022-03-16 09:49:54 -07:00
|
|
|
locations."/" = {
|
|
|
|
proxyPass = "http://127.0.0.1:${toString cfg.loki.port}";
|
2023-10-14 16:15:26 -07:00
|
|
|
extraConfig = let local-networks = config.instance.local-networks;
|
2022-03-16 09:49:54 -07:00
|
|
|
in "${optionalString ((length local-networks) > 0)
|
2023-10-14 16:15:26 -07:00
|
|
|
(concatStringsSep "\n"
|
|
|
|
(map (network: "allow ${network};") local-networks)) + ''
|
|
|
|
|
|
|
|
deny all;''}";
|
2022-03-16 09:49:54 -07:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
loki = mkIf isLogAggregator {
|
|
|
|
enable = true;
|
|
|
|
dataDir = cfg.loki.state-directory;
|
|
|
|
# cargo-culted from https://gist.github.com/Xe/c3c786b41ec2820725ee77a7af551225
|
|
|
|
configuration = {
|
|
|
|
auth_enabled = false;
|
|
|
|
|
|
|
|
server.http_listen_port = cfg.loki.port;
|
|
|
|
|
|
|
|
ingester = {
|
|
|
|
lifecycler = {
|
|
|
|
address = "127.0.0.1";
|
|
|
|
ring = {
|
|
|
|
kvstore.store = "inmemory";
|
|
|
|
replication_factor = 1;
|
|
|
|
};
|
|
|
|
final_sleep = "0s";
|
|
|
|
};
|
|
|
|
chunk_idle_period = "1h";
|
|
|
|
max_chunk_age = "1h";
|
|
|
|
chunk_target_size = 10485576;
|
|
|
|
chunk_retain_period = "30s";
|
|
|
|
max_transfer_retries = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
compactor = {
|
|
|
|
working_directory = "${cfg.loki.state-directory}/compactor";
|
|
|
|
};
|
|
|
|
|
2023-10-14 16:15:26 -07:00
|
|
|
schema_config.configs = [{
|
|
|
|
from = "2022-01-01";
|
|
|
|
store = "boltdb-shipper";
|
|
|
|
object_store = "filesystem";
|
|
|
|
schema = "v11";
|
|
|
|
index = {
|
|
|
|
prefix = "index_";
|
|
|
|
period = "24h";
|
|
|
|
};
|
|
|
|
}];
|
2022-03-16 09:49:54 -07:00
|
|
|
|
|
|
|
storage_config = {
|
|
|
|
boltdb_shipper = {
|
2023-10-14 16:15:26 -07:00
|
|
|
active_index_directory =
|
|
|
|
"${cfg.loki.state-directory}/boltdb-shipper/active";
|
|
|
|
cache_location =
|
|
|
|
"${cfg.loki.state-directory}/boltdb-shipper/cache";
|
2022-03-16 09:49:54 -07:00
|
|
|
cache_ttl = "24h";
|
|
|
|
shared_store = "filesystem";
|
|
|
|
};
|
|
|
|
filesystem.directory = "${cfg.loki.state-directory}/chunks";
|
|
|
|
};
|
|
|
|
|
|
|
|
limits_config = {
|
|
|
|
reject_old_samples = true;
|
|
|
|
reject_old_samples_max_age = "168h";
|
|
|
|
};
|
|
|
|
|
|
|
|
chunk_store_config.max_look_back_period = "0s";
|
|
|
|
|
|
|
|
table_manager = {
|
|
|
|
retention_deletes_enabled = false;
|
|
|
|
retention_period = "0s";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-10-14 16:15:26 -07:00
|
|
|
systemd = let
|
|
|
|
lokiUser = config.services.loki.user;
|
|
|
|
statedir = cfg.loki.state-directory;
|
|
|
|
in {
|
|
|
|
tmpfiles.rules = optionals isLogAggregator [
|
|
|
|
"d ${statedir} 0700 ${lokiUser} - - -"
|
|
|
|
"d ${statedir}/boltdb-shipper 0700 ${lokiUser} - - -"
|
|
|
|
"d ${statedir}/boltdb-shipper/active 0700 ${lokiUser} - - -"
|
|
|
|
"d ${statedir}/boltdb-shipper/cache 0700 ${lokiUser} - - -"
|
|
|
|
"d ${statedir}/chunks 0700 ${lokiUser} - - -"
|
|
|
|
"d ${statedir}/compactor 0700 ${lokiUser} - - -"
|
|
|
|
];
|
|
|
|
|
|
|
|
services = {
|
|
|
|
loki.serviceConfig = mkIf isLogAggregator {
|
|
|
|
ExecStartPre =
|
|
|
|
"+${pkgs.coreutils}/bin/chown -R ${lokiUser}:root ${statedir}";
|
|
|
|
};
|
|
|
|
|
|
|
|
promtail = let
|
|
|
|
scheme = if is-private-network then "http" else "https";
|
|
|
|
|
|
|
|
loki-host = host-fqdn domain.log-aggregator;
|
|
|
|
|
|
|
|
config = builtins.toJSON {
|
|
|
|
server = {
|
|
|
|
http_listen_port = cfg.promtail.http-listen-port;
|
|
|
|
grpc_listen_port = cfg.promtail.grpc-listen-port;
|
|
|
|
};
|
|
|
|
positions.filename = "/tmp/positions.yml";
|
|
|
|
clients = [{
|
|
|
|
url =
|
|
|
|
"${scheme}://log-aggregator.${domain-name}/loki/api/v1/push";
|
|
|
|
}];
|
|
|
|
scrape_configs = [{
|
2022-03-16 09:49:54 -07:00
|
|
|
job_name = "journal";
|
|
|
|
journal = {
|
|
|
|
max_age = "12h";
|
|
|
|
labels = {
|
|
|
|
job = "systemd-journal";
|
|
|
|
host = hostname;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
relabel_configs = [{
|
|
|
|
source_labels = [ "__journal__systemd_unit" ];
|
|
|
|
target_label = "unit";
|
|
|
|
}];
|
2023-10-14 16:15:26 -07:00
|
|
|
}];
|
|
|
|
};
|
2022-03-16 09:49:54 -07:00
|
|
|
|
2023-10-14 16:15:26 -07:00
|
|
|
config-file = pkgs.writeText "promtail-config.json" config;
|
|
|
|
in {
|
|
|
|
description = "PromTail log aggregator client for Loki.";
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
serviceConfig = {
|
|
|
|
ExecStart = ''
|
|
|
|
${pkgs.grafana-loki}/bin/promtail --config.file ${config-file}
|
|
|
|
'';
|
|
|
|
User = cfg.promtail.user;
|
|
|
|
PrivateTmp = true;
|
|
|
|
};
|
2022-03-16 09:49:54 -07:00
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|