Compare commits

..

No commits in common. "03795a46a76499a5ab512cd749c8128a27756d06" and "52eb5d90d958d4acf4cba9fb902db100c5784dbb" have entirely different histories.

10 changed files with 205 additions and 849 deletions

1
.pre-commit-config.yaml Symbolic link
View file

@ -0,0 +1 @@
/nix/store/1w2s62i701n28sj08gn1445qr4v3vijp-pre-commit-config.json

122
flake.lock generated
View file

@ -15,11 +15,11 @@
"uv2nix": "uv2nix" "uv2nix": "uv2nix"
}, },
"locked": { "locked": {
"lastModified": 1776085803, "lastModified": 1772909021,
"narHash": "sha256-JvvWVbXJYSY8qOReMbAOD4lxcN2cjKV6lg/jLz8CEuY=", "narHash": "sha256-hcstQ1Z9aQSJM3AVCLb0/OPTicbME9nhP01GiPrOjZM=",
"owner": "nix-community", "owner": "nix-community",
"repo": "authentik-nix", "repo": "authentik-nix",
"rev": "4370b561c8bafb59773ce3a518506bcf1161dbdb", "rev": "7e4730351fb6df479c46a1bf7e23d46a0b0c5d46",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -47,16 +47,16 @@
"authentik-src": { "authentik-src": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1775573258, "lastModified": 1772567399,
"narHash": "sha256-Xq7JGI/8ppIydIuWd9KRJKUrh7UpeniwvZ4NAtXbYJ4=", "narHash": "sha256-0Vpf1hj9C8r+rhrCgwoNazpQ+mwgjdjDhuoKCxYQFWw=",
"owner": "goauthentik", "owner": "goauthentik",
"repo": "authentik", "repo": "authentik",
"rev": "5249546862986202b901c2afd860992ec48c6ef6", "rev": "0dccbd4193c45c581e9fb7cd89df0c1487510f1f",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "goauthentik", "owner": "goauthentik",
"ref": "version/2026.2.2", "ref": "version/2026.2.1",
"repo": "authentik", "repo": "authentik",
"type": "github" "type": "github"
} }
@ -84,11 +84,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1776613567, "lastModified": 1773025010,
"narHash": "sha256-gC9Cp5ibBmGD5awCA9z7xy6MW6iJufhazTYJOiGlCUI=", "narHash": "sha256-khlHllTsovXgT2GZ0WxT4+RvuMjNeR5OW0UYeEHPYQo=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "32f4236bfc141ae930b5ba2fb604f561fed5219d", "rev": "7b9f7f88ab3b339f8142dc246445abb3c370d3d3",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -118,11 +118,27 @@
"locked": { "locked": {
"lastModified": 1767039857, "lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=", "narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "edolstra", "owner": "NixOS",
"repo": "flake-compat", "repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab", "rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github" "type": "github"
}, },
"original": {
"owner": "NixOS",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_3": {
"flake": false,
"locked": {
"lastModified": 1761588595,
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
"type": "github"
},
"original": { "original": {
"owner": "edolstra", "owner": "edolstra",
"repo": "flake-compat", "repo": "flake-compat",
@ -170,13 +186,9 @@
}, },
"git-hooks": { "git-hooks": {
"inputs": { "inputs": {
"flake-compat": [ "flake-compat": "flake-compat_2",
"mailserver",
"flake-compat"
],
"gitignore": "gitignore", "gitignore": "gitignore",
"nixpkgs": [ "nixpkgs": [
"mailserver",
"nixpkgs" "nixpkgs"
] ]
}, },
@ -194,7 +206,54 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks_2": {
"inputs": {
"flake-compat": [
"mailserver",
"flake-compat"
],
"gitignore": "gitignore_2",
"nixpkgs": [
"mailserver",
"nixpkgs"
]
},
"locked": {
"lastModified": 1763319842,
"narHash": "sha256-YG19IyrTdnVn0l3DvcUYm85u3PaqBt6tI6VvolcuHnA=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "7275fa67fbbb75891c16d9dee7d88e58aea2d761",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": { "gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"gitignore_2": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
"mailserver", "mailserver",
@ -219,16 +278,16 @@
"mailserver": { "mailserver": {
"inputs": { "inputs": {
"blobs": "blobs", "blobs": "blobs",
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat_3",
"git-hooks": "git-hooks", "git-hooks": "git-hooks_2",
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
}, },
"locked": { "locked": {
"lastModified": 1773912645, "lastModified": 1773313890,
"narHash": "sha256-QHzRqq6gh+t3F/QU9DkP7X63dDDcuIQmaDz12p7ANTg=", "narHash": "sha256-NXm/kOAk7HLziH1uWaUbNb9MhDS8yxFfQ8fMK5eN8/A=",
"ref": "nixos-25.11", "ref": "nixos-25.11",
"rev": "25e6dbb8fca3b6e779c5a46fd03bd760b2165bb5", "rev": "9cdd6869e513df8153db4b920c8f15d394e150f7",
"revCount": 843, "revCount": 842,
"type": "git", "type": "git",
"url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver" "url": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver"
}, },
@ -297,11 +356,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1773831496, "lastModified": 1764020296,
"narHash": "sha256-JW2/QPyCVzmouqEp1H9kNa8JXd7xEhlam9sy3TYfhDY=", "narHash": "sha256-6zddwDs2n+n01l+1TG6PlyokDdXzu/oBmEejcH5L5+A=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "826430a188181a750ffa5948daff334039c5d741", "rev": "a320ce8e6e2cc6b4397eef214d202a50a4583829",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -313,11 +372,11 @@
}, },
"nixpkgs_3": { "nixpkgs_3": {
"locked": { "locked": {
"lastModified": 1776734388, "lastModified": 1773222311,
"narHash": "sha256-vl3dkhlE5gzsItuHoEMVe+DlonsK+0836LIRDnm6MXQ=", "narHash": "sha256-BHoB/XpbqoZkVYZCfXJXfkR+GXFqwb/4zbWnOr2cRcU=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "10e7ad5bbcb421fe07e3a4ad53a634b0cd57ffac", "rev": "0590cd39f728e129122770c029970378a79d076a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -381,6 +440,7 @@
"inputs": { "inputs": {
"authentik": "authentik", "authentik": "authentik",
"disko": "disko", "disko": "disko",
"git-hooks": "git-hooks",
"mailserver": "mailserver", "mailserver": "mailserver",
"nixpkgs": "nixpkgs_3", "nixpkgs": "nixpkgs_3",
"sops": "sops" "sops": "sops"
@ -393,11 +453,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1776771786, "lastModified": 1773096132,
"narHash": "sha256-DRFGPfFV6hbrfO9a1PH1FkCi7qR5FgjSqsQGGvk1rdI=", "narHash": "sha256-M3zEnq9OElB7zqc+mjgPlByPm1O5t2fbUrH3t/Hm5Ag=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "bef289e2248991f7afeb95965c82fbcd8ff72598", "rev": "d1ff3b1034d5bab5d7d8086a7803c5a5968cd784",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -18,6 +18,10 @@
url = "github:nix-community/disko"; url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = outputs =
@ -28,6 +32,7 @@
mailserver, mailserver,
disko, disko,
sops, sops,
git-hooks,
}: }:
let let
sshkeys = [ sshkeys = [
@ -42,6 +47,12 @@
devShells.x86_64-linux.default = devShells.x86_64-linux.default =
let let
pkgs = nixpkgs.legacyPackages.x86_64-linux; pkgs = nixpkgs.legacyPackages.x86_64-linux;
pre-commit-check = git-hooks.lib.x86_64-linux.run {
src = ./.;
hooks = {
nixfmt-rfc-style.enable = true;
};
};
in in
pkgs.mkShell { pkgs.mkShell {
# Import GPG keys from keys directory # Import GPG keys from keys directory
@ -53,11 +64,15 @@
# Isolate sops GPG keys to .git/gnupg (optional) # Isolate sops GPG keys to .git/gnupg (optional)
# sopsCreateGPGHome = true; # sopsCreateGPGHome = true;
shellHook = ''
${pre-commit-check.shellHook}
'';
nativeBuildInputs = [ nativeBuildInputs = [
sops.packages.x86_64-linux.sops-import-keys-hook sops.packages.x86_64-linux.sops-import-keys-hook
]; ];
buildInputs = [ buildInputs = pre-commit-check.enabledPackages ++ [
pkgs.sops pkgs.sops
]; ];
}; };
@ -193,7 +208,6 @@
[ [
./hosts/${input} ./hosts/${input}
./default.nix ./default.nix
./modules/monitoring.nix
disko.nixosModules.disko disko.nixosModules.disko
authentik.nixosModules.default authentik.nixosModules.default
mailserver.nixosModules.mailserver mailserver.nixosModules.mailserver

View file

@ -1,246 +0,0 @@
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
"${modulesPath}/virtualisation/proxmox-lxc.nix"
];
networking = {
hostName = "monitoring";
fqdn = "monitoring.adm.htw.stura-dresden.de";
interfaces.eth0.ipv4.addresses = [
{
address = "141.56.51.20";
prefixLength = 24;
}
];
defaultGateway = {
address = "141.56.51.254";
interface = "eth0";
};
firewall = {
enable = true;
allowedTCPPorts = [
80
443
4317 # OTLP gRPC (Proxmox)
4318 # OTLP HTTP (Proxmox)
];
};
};
# Loki - Log aggregation system
services.loki = {
enable = true;
configuration = {
auth_enabled = false;
server = {
http_listen_port = 3100;
grpc_listen_port = 9096;
};
common = {
path_prefix = "/var/lib/loki";
storage.filesystem = {
chunks_directory = "/var/lib/loki/chunks";
rules_directory = "/var/lib/loki/rules";
};
replication_factor = 1;
ring = {
instance_addr = "127.0.0.1";
kvstore.store = "inmemory";
};
};
limits_config = {
ingestion_rate_mb = 32;
ingestion_burst_size_mb = 64;
per_stream_rate_limit = "32MB";
per_stream_rate_limit_burst = "64MB";
max_query_series = 100000;
retention_period = "672h"; # 28 days
};
compactor = {
retention_enabled = true;
working_directory = "/var/lib/loki/compactor";
delete_request_store = "filesystem";
};
schema_config = {
configs = [
{
from = "2024-01-01";
store = "tsdb";
object_store = "filesystem";
schema = "v13";
index = {
prefix = "index_";
period = "24h";
};
}
];
};
};
};
# Mimir - Scalable metrics storage
services.mimir = {
enable = true;
configuration = {
multitenancy_enabled = false;
memberlist = {
bind_addr = [ "0.0.0.0" ];
bind_port = 7946;
advertise_addr = "141.56.51.20";
join_members = [ "141.56.51.20:7946" ];
};
blocks_storage = {
backend = "filesystem";
filesystem = {
dir = "/var/lib/mimir/data";
};
};
compactor = {
data_dir = "/var/lib/mimir/compactor";
};
distributor = {
ring = {
kvstore.store = "memberlist";
};
};
ingester = {
ring = {
kvstore.store = "memberlist";
replication_factor = 1;
};
};
ruler_storage = {
backend = "filesystem";
filesystem = {
dir = "/var/lib/mimir/rules";
};
};
server = {
http_listen_port = 9009;
grpc_listen_port = 9095;
};
limits = {
ingestion_rate = 100000;
ingestion_burst_size = 200000;
max_global_series_per_user = 0;
compactor_blocks_retention_period = "672h"; # 28 days
};
store_gateway = {
sharding_ring = {
replication_factor = 1;
kvstore.store = "memberlist";
};
};
};
};
# Grafana - Visualization and dashboarding
services.grafana = {
enable = true;
settings = {
server = {
http_addr = "127.0.0.1";
http_port = 3000;
domain = "mon.adm.htw.stura-dresden.de";
root_url = "https://mon.adm.htw.stura-dresden.de";
};
security = {
admin_user = "admin";
admin_password = "$__file{/var/lib/grafana/admin_password}";
};
};
provision = {
enable = true;
datasources.settings.datasources = [
{
name = "Mimir";
type = "prometheus";
url = "http://localhost:9009/prometheus";
isDefault = true;
}
{
name = "Loki";
type = "loki";
url = "http://localhost:3100";
}
];
};
};
# Nginx reverse proxy with ACME certificates
services.nginx = {
enable = true;
virtualHosts."log.adm.htw.stura-dresden.de" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3100";
proxyWebsockets = true;
recommendedProxySettings = true;
};
};
virtualHosts."met.adm.htw.stura-dresden.de" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:9009";
recommendedProxySettings = true;
};
};
virtualHosts."mon.adm.htw.stura-dresden.de" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3000";
proxyWebsockets = true;
recommendedProxySettings = true;
};
};
};
# Vector - receive OpenTelemetry data from Proxmox and forward to Loki/Mimir
services.vector.settings = {
sources.proxmox_otlp = {
type = "opentelemetry";
grpc.address = "0.0.0.0:4317";
http.address = "0.0.0.0:4318";
};
transforms.proxmox_normalize_logs = {
type = "remap";
inputs = [ "proxmox_otlp.logs" ];
source = ''
.host = string(.resources."host.name") ?? "proxmox"
.unit = string(.attributes."service.name") ?? "proxmox"
'';
};
transforms.proxmox_normalize_metrics = {
type = "remap";
inputs = [ "proxmox_otlp.metrics" ];
source = ''
.tags.host = string(.resources."host.name") ?? "proxmox"
'';
};
};
stura.monitoring = {
extraMetricInputs = [ "proxmox_normalize_metrics" ];
extraLogInputs = [ "proxmox_normalize_logs" ];
};
services.openssh.enable = true;
system.stateVersion = "25.11";
}

View file

@ -87,11 +87,6 @@
recommendedProxySettings = true; recommendedProxySettings = true;
recommendedTlsSettings = true; recommendedTlsSettings = true;
commonHttpConfig = ''
real_ip_header proxy_protocol;
set_real_ip_from 141.56.51.1/32;
'';
logError = '' logError = ''
/dev/null emerg /dev/null emerg
''; '';
@ -99,21 +94,9 @@
virtualHosts.${config.networking.fqdn} = { virtualHosts.${config.networking.fqdn} = {
forceSSL = true; forceSSL = true;
enableACME = true; enableACME = true;
listen = [ extraConfig = ''
{ access_log off;
port = 80; '';
addr = "0.0.0.0";
}
{
port = 443;
addr = "0.0.0.0";
ssl = true;
proxyProtocol = true;
}
];
# extraConfig = ''
# access_log off;
# '';
}; };
# virtualHosts."cloud.htw.stura-dresden.de" = { # virtualHosts."cloud.htw.stura-dresden.de" = {
# forceSSL = true; # forceSSL = true;

View file

@ -20,99 +20,25 @@
} }
]; ];
defaultGateway.address = "141.56.51.254"; defaultGateway.address = "141.56.51.254";
firewall.enable = false; firewall = {
allowedTCPPorts = [
22
53 # DNS
80
443
1005
2142
];
allowedUDPPorts = [
53 # DNS
123 # NTP
];
};
nftables = { nftables = {
enable = true; enable = true;
ruleset = ''
table inet filter {
set blacklist4 {
type ipv4_addr
flags interval
# manage: nft add element inet filter blacklist4 { 1.2.3.0/24 }
}
set blacklist6 {
type ipv6_addr
flags interval
# manage: nft add element inet filter blacklist6 { 2001:db8::/32 }
}
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
ip saddr 141.56.51.0/24 accept
ip saddr @blacklist4 drop
ip6 saddr @blacklist6 drop
# public ports
tcp dport { 80, 443, 1005, 2142 } accept
# lan-only: dns and ntp
ip saddr 141.56.51.0/24 tcp dport 53 accept
ip saddr 141.56.51.0/24 udp dport { 53, 123 } accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
'';
}; };
}; };
# Phase 1: Kernel-Level TCP Tuning
boot.kernel.sysctl = {
# Connection tracking - prevents "table full" errors
"net.netfilter.nf_conntrack_max" = 262144; # Conservative limit matching current kernel
"net.netfilter.nf_conntrack_buckets" = 65536; # 4:1 ratio
# Reduce connection tracking timeouts (defaults are excessive)
"net.netfilter.nf_conntrack_tcp_timeout_established" = 600; # 10 min (down from 5 days)
"net.netfilter.nf_conntrack_tcp_timeout_time_wait" = 30; # 30s
"net.netfilter.nf_conntrack_tcp_timeout_close_wait" = 15; # 15s
"net.netfilter.nf_conntrack_tcp_timeout_fin_wait" = 30; # 30s
# TCP connection handling
"net.core.somaxconn" = 65535; # Must be >= HAProxy maxconn
"net.core.netdev_max_backlog" = 16384;
"net.ipv4.tcp_max_syn_backlog" = 8192;
# TCP buffer auto-tuning (16MB max)
"net.ipv4.tcp_rmem" = "4096 87380 16777216";
"net.ipv4.tcp_wmem" = "4096 65536 16777216";
"net.core.rmem_max" = 16777216;
"net.core.wmem_max" = 16777216;
# TCP optimization
"net.ipv4.tcp_fin_timeout" = 15;
"net.ipv4.tcp_keepalive_time" = 300; # 5 min
"net.ipv4.tcp_keepalive_probes" = 3;
"net.ipv4.tcp_keepalive_intvl" = 15;
# TCP Fast Open
"net.ipv4.tcp_fastopen" = 3;
# BBR congestion control for better throughput
"net.ipv4.tcp_congestion_control" = "bbr";
"net.core.default_qdisc" = "fq";
# Ephemeral port range
"net.ipv4.ip_local_port_range" = "10000 65535";
# TIME_WAIT socket reuse
"net.ipv4.tcp_tw_reuse" = 1;
};
# Enable BBR kernel module
boot.kernelModules = [ "tcp_bbr" ];
# wenn instanzen in die flake migriert sind könnte man das autogenerierien # wenn instanzen in die flake migriert sind könnte man das autogenerierien
services = services =
let let
@ -126,112 +52,96 @@
domain = "docs.adm.htw.stura-dresden.de"; domain = "docs.adm.htw.stura-dresden.de";
httpPort = 8080; httpPort = 8080;
httpsPort = 8443; httpsPort = 8443;
sendProxy = false;
}; };
plone = { plone = {
dest = "141.56.51.3"; dest = "141.56.51.3";
domain = "stura.htw-dresden.de"; domain = "stura.htw-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = true;
}; };
plone_alt = { plone_alt = {
dest = "141.56.51.3"; dest = "141.56.51.3";
domain = "www.stura.htw-dresden.de"; domain = "www.stura.htw-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = true;
}; };
plone_neu = { plone_neu = {
dest = "141.56.51.3"; dest = "141.56.51.3";
domain = "www.htw.stura-dresden.de"; domain = "www.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = true;
}; };
plone_neu2 = { plone_neu2 = {
dest = "141.56.51.3"; dest = "141.56.51.3";
domain = "htw.stura-dresden.de"; domain = "htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = true;
}; };
tix = { tix = {
dest = "141.56.51.220"; dest = "141.56.51.220";
domain = "tix.htw.stura-dresden.de"; domain = "tix.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false;
}; };
post = { post = {
dest = "141.56.51.56"; dest = "141.56.51.56";
domain = "post.htw.stura-dresden.de"; domain = "post.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false;
}; };
vot = { vot = {
dest = "141.56.51.57"; dest = "141.56.51.57";
domain = "vot.htw.stura-dresden.de"; domain = "vot.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false;
}; };
mail = { mail = {
dest = "141.56.51.14"; dest = "141.56.51.14";
domain = "mail.htw.stura-dresden.de"; domain = "mail.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false;
}; };
lists = { lists = {
dest = "141.56.51.14"; dest = "141.56.51.14";
domain = "lists.htw.stura-dresden.de"; domain = "lists.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false;
}; };
dat = { dat = {
dest = "141.56.51.17"; dest = "141.56.51.17";
domain = "dat.stu.htw.stura-dresden.de"; domain = "dat.stu.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false; };
pro = {
dest = "141.56.51.15";
domain = "pro.htw.stura-dresden.de";
httpPort = 80;
httpsPort = 443;
};
cloud = {
dest = "141.56.51.16";
domain = "cloud.htw.stura-dresden.de";
httpPort = 80;
httpsPort = 443;
}; };
wiki = { wiki = {
dest = "141.56.51.13"; dest = "141.56.51.13";
domain = "wiki.htw.stura-dresden.de"; domain = "wiki.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = true;
}; };
beach = { beach = {
dest = "141.56.51.51"; dest = "141.56.51.51";
domain = "beach.htw.stura-dresden.de"; domain = "beach.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false;
}; };
studicloud = { studicloud = {
dest = "141.56.51.17"; dest = "141.56.51.17";
domain = "dat.stu.htw.stura-dresden.de"; domain = "dat.stu.htw.stura-dresden.de";
httpPort = 80; httpPort = 80;
httpsPort = 443; httpsPort = 443;
sendProxy = false;
};
bbb = {
dest = "141.56.51.94";
domain = "bbb.htw.stura-dresden.de";
httpPort = 80;
httpsPort = 443;
sendProxy = false;
};
bbb-test = {
dest = "141.56.51.94";
domain = "bbb.test.htw.stura-dresden.de";
httpPort = 80;
httpsPort = 443;
sendProxy = false;
}; };
} }
# zusätzlich zu den oben definierten wird hier noch ein redirect für jeden nginx virtualhost in diese flake generiert # zusätzlich zu den oben definierten wird hier noch ein redirect für jeden nginx virtualhost in diese flake generiert
@ -250,15 +160,6 @@
prev prev
// (builtins.foldl' ( // (builtins.foldl' (
val: vhost: val: vhost:
let
proxyProtocol =
if
self.nixosConfigurations.${name}.config.services.nginx.virtualHosts.${vhost}.listen == [ ]
then
false
else
true;
in
val val
// { // {
"${vhost}" = { "${vhost}" = {
@ -266,7 +167,6 @@
domain = vhost; domain = vhost;
httpsPort = 443; httpsPort = 443;
httpPort = 80; httpPort = 80;
sendProxy = proxyProtocol;
}; };
} }
) { } vhosts) ) { } vhosts)
@ -323,43 +223,43 @@
"127.0.0.1" "127.0.0.1"
]; ];
listenOnIpv6 = [ ]; listenOnIpv6 = [ ];
# zones = { zones = {
# "htw.stura-dresden.de" = { "htw.stura-dresden.de" = {
# master = true; master = true;
# file = pkgs.writeText "htw.stura-dresden.de.zone" '' file = pkgs.writeText "htw.stura-dresden.de.zone" ''
# $TTL 3600 $TTL 3600
# @ IN SOA proxy.htw.stura-dresden.de. hostmaster.htw.stura-dresden.de. ( @ IN SOA proxy.htw.stura-dresden.de. hostmaster.htw.stura-dresden.de. (
# 2026031301 ; Serial (YYYYMMDDNN) 2026031301 ; Serial (YYYYMMDDNN)
# 3600 ; Refresh (1 hour) 3600 ; Refresh (1 hour)
# 1800 ; Retry (30 minutes) 1800 ; Retry (30 minutes)
# 604800 ; Expire (1 week) 604800 ; Expire (1 week)
# 86400 ) ; Minimum TTL (1 day) 86400 ) ; Minimum TTL (1 day)
#
# ; Name servers ; Name servers
# @ IN NS proxy.htw.stura-dresden.de. @ IN NS proxy.htw.stura-dresden.de.
#
# ; Proxy host - main IPv4 gateway ; Proxy host - main IPv4 gateway
# proxy IN A 141.56.51.1 proxy IN A 141.56.51.1
# proxy IN AAAA 2a01:4f8:1c19:96f8::1 proxy IN AAAA 2a01:4f8:1c19:96f8::1
#
# ; Auto-generated CNAME records for all subdomains pointing to proxy ; Auto-generated CNAME records for all subdomains pointing to proxy
# ${lib.foldlAttrs ( ${lib.foldlAttrs (
# prev: name: value: prev: name: value:
# let let
# zoneSuffix = ".htw.stura-dresden.de"; zoneSuffix = ".htw.stura-dresden.de";
# # Check if this domain belongs to our zone # Check if this domain belongs to our zone
# isInZone = lib.hasSuffix zoneSuffix value.domain; isInZone = lib.hasSuffix zoneSuffix value.domain;
# # Extract subdomain by removing the zone suffix # Extract subdomain by removing the zone suffix
# subdomain = lib.removeSuffix zoneSuffix value.domain; subdomain = lib.removeSuffix zoneSuffix value.domain;
# in in
# if isInZone && subdomain != "" && subdomain != "htw.stura-dresden.de" then if isInZone && subdomain != "" && subdomain != "htw.stura-dresden.de" then
# prev + "${subdomain}${" "}IN${" "}CNAME${" "}proxy.htw.stura-dresden.de.\n" prev + "${subdomain}${" "}IN${" "}CNAME${" "}proxy.htw.stura-dresden.de.\n"
# else else
# prev prev
# ) "" forwards} ) "" forwards}
# ''; '';
# }; };
# }; };
}; };
# Chrony NTP server for the internal network # Chrony NTP server for the internal network
@ -435,35 +335,18 @@
global global
# schreibe globalen log ins journal ip -> app # schreibe globalen log ins journal ip -> app
log /dev/log format raw local0 log /dev/log format raw local0
maxconn 60000 # Safe limit below kernel conntrack (262144) maxconn 50000
# man könnte metriken über einen socket file statt einen lokalen port machen für user permission control
# Buffer optimizations (Phase 2) # stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
tune.bufsize 32768 # Power of 2 (was 32762) tune.bufsize 32762
tune.maxrewrite 8192
# Connection handling
tune.maxaccept 500 # Prevent accept starvation
tune.maxpollevents 300
# TCP buffer sizes (64KB)
tune.rcvbuf.client 65536
tune.rcvbuf.server 65536
tune.sndbuf.client 65536
tune.sndbuf.server 65536
defaults defaults
log global log global
mode tcp mode tcp
option tcplog option tcplog
timeout connect 5s
# Optimized timeouts (Phase 5) timeout client 30s
timeout connect 3s # Reduce from 5s timeout server 30s
timeout client 60s # Increase from 30s
timeout server 60s # Increase from 30s
timeout queue 5s # Prevent indefinite queueing
# Performance
option splice-auto # Zero-copy kernel splicing
# stats seite zeigt backend connection status, wenn check gesetzt ist # stats seite zeigt backend connection status, wenn check gesetzt ist
frontend stats frontend stats
@ -471,21 +354,13 @@
mode http mode http
stats enable stats enable
stats uri /stats stats uri /stats
stats refresh 5s # Reduce from 10s for real-time monitoring stats refresh 10s
stats show-legends stats show-legends
stats show-node stats show-node
stats show-modules stats show-modules
stats admin if TRUE # Enable admin operations
http-request use-service prometheus-exporter if { path /metrics }
frontend http-in frontend http-in
bind *:80 bind *:80
mode http
tcp-request connection expect-proxy layer4 if { src 178.104.18.93 }
maxconn 60000
backlog 8192
option dontlognull
option http-keep-alive # Reuse connections for redirects
# hier wird eine regel pro domain aus der forwarder liste generiert # hier wird eine regel pro domain aus der forwarder liste generiert
${lib.foldlAttrs ( ${lib.foldlAttrs (
@ -504,8 +379,8 @@
prev: name: value: prev: name: value:
prev prev
+ '' + ''
http-request redirect scheme https code 301 if !is_acme is_${name}
use_backend ${name}_80 if is_${name} use_backend ${name}_80 if is_${name}
http-request redirect scheme https code 301 if !is_acme is_${name}
'' ''
) "" forwards} ) "" forwards}
@ -526,18 +401,10 @@
frontend sni_router frontend sni_router
bind *:443 bind *:443
mode tcp mode tcp
tcp-request connection expect-proxy layer4 if { src 178.104.18.93 } # mehrere pakete puffern und connection beenden wenn es kein ssl handshake sieht
tcp-request inspect-delay 1s
# Reduce inspection delay - SNI is in first packet (Phase 3)
tcp-request inspect-delay 500ms # Was 1s
tcp-request content accept if { req_ssl_hello_type 1 } tcp-request content accept if { req_ssl_hello_type 1 }
# Connection handling
option clitcpka # Enable client TCP keep-alive
maxconn 60000
backlog 16384 # Increase from default 1024
option dontlognull # Skip logging of monitoring probes
# tcp redirect der anwendung basierend auf ssl_sni handshake parameter # tcp redirect der anwendung basierend auf ssl_sni handshake parameter
${lib.foldlAttrs ( ${lib.foldlAttrs (
prev: name: value: prev: name: value:
@ -568,118 +435,14 @@
server ${name} ${value.dest}:${builtins.toString value.httpPort} server ${name} ${value.dest}:${builtins.toString value.httpPort}
backend ${name}_443 backend ${name}_443
mode tcp mode tcp
option tcpka # Enable server TCP keep-alive (Phase 4) server ${name} ${value.dest}:${builtins.toString value.httpsPort} check
timeout server 60s # Increase from 30s for long-lived HTTPS
timeout connect 3s # Reduce from 5s (local network)
server ${name} ${value.dest}:${builtins.toString value.httpsPort} ${
if value.sendProxy == true then "send-proxy-v2" else ""
} check inter 3000 rise 2 fall 3 maxconn 5000
'' ''
) "" forwards} ) "" forwards}
''; '';
}; };
vector.settings = {
enrichment_tables.geoip_table = {
type = "mmdb";
path = "/var/lib/GeoIP/GeoLite2-City.mmdb";
};
sources.haproxy_metrics = {
type = "prometheus_scrape";
endpoints = [ "http://127.0.0.1:8404/metrics" ];
scrape_interval_secs = 15;
};
transforms = {
add_host_label_haproxy = {
type = "remap";
inputs = [ "haproxy_metrics" ];
source = ''
.tags.host = get_hostname!()
'';
};
haproxy_logs_filter = {
type = "filter";
inputs = [ "journald_logs" ];
condition = ''."_SYSTEMD_UNIT" == "haproxy.service"'';
};
haproxy_logs_parse = {
type = "remap";
inputs = [ "haproxy_logs_filter" ];
source = ''
.host = get_hostname!()
.unit = "haproxy"
# IPv4: "1.2.3.4:port" IPv6: "[2001:db8::1]:port"
parsed, err = parse_regex(.message, r'^(?:\[(?P<ipv6>[0-9a-fA-F:]+)\]|(?P<ipv4>[\d.]+)):\d+')
if err == null {
if is_null(parsed.ipv6) {
.client_ip = parsed.ipv4
} else {
.client_ip = parsed.ipv6
}
}
'';
};
haproxy_geoip = {
type = "remap";
inputs = [ "haproxy_logs_parse" ];
source = ''
if exists(.client_ip) && !is_null(.client_ip) {
.geoip = get_enrichment_table_record("geoip_table", {"ip": string!(.client_ip)}) ?? {}
}
'';
};
};
sinks.mimir.inputs = lib.mkForce [
"add_host_label_metrics"
"add_host_label_haproxy"
];
};
}; };
stura.monitoring.extraLogInputs = [ "haproxy_geoip" ];
users.users.root.packages = [
(pkgs.writeShellScriptBin "nft-blacklist" ''
set -euo pipefail
usage() {
echo "Usage: nft-blacklist <add|del> <ip-or-cidr>"
echo " add - add entry to blacklist set"
echo " del - remove entry from blacklist set"
exit 1
}
[[ $# -ne 2 ]] && usage
ACTION="$1"
ADDR="$2"
if [[ "$ADDR" == *:* ]]; then
SET="blacklist6"
elif [[ "$ADDR" == *.* ]]; then
SET="blacklist4"
else
echo "Error: cannot determine address family for '$ADDR'" >&2
exit 1
fi
case "$ACTION" in
add)
${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }"
echo "Added $ADDR to $SET"
;;
del)
${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }"
echo "Removed $ADDR from $SET"
;;
*)
usage
;;
esac
'')
];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
]; ];

View file

@ -90,9 +90,7 @@
services.redmine.settings.production.email_delivery = { services.redmine.settings.production.email_delivery = {
delivery_method = ":smtp"; delivery_method = ":smtp";
smtp_settings = { smtp_settings = {
# @tan 27-03-2026: muss an "alten" mailserver senden address = "mail.${config.networking.domain}";
#address = "mail.${config.networking.domain}";
address = "mail.stura.htw-dresden.de";
port = 25; port = 25;
}; };
#### Alternativ waere vielleicht auch das Versand von Mails durch das Programm sendmail (als lokale Installation) moeglich. #### Alternativ waere vielleicht auch das Versand von Mails durch das Programm sendmail (als lokale Installation) moeglich.
@ -134,29 +132,13 @@
#### Der StuRa speichert nicht! #### Der StuRa speichert nicht!
services.nginx.logError = ''/dev/null emerg''; services.nginx.logError = ''/dev/null emerg'';
# services.nginx.appendHttpConfig = '' services.nginx.appendHttpConfig = ''
# access_log off; access_log off;
# '';
services.nginx.commonHttpConfig = ''
real_ip_header proxy_protocol;
set_real_ip_from 141.56.51.1/32;
''; '';
#### Anscheinend kann mit nix nur die Konfiguration fuer eine konkrete (manuelle) Konfiguration fuer den Dienst web server. #### Anscheinend kann mit nix nur die Konfiguration fuer eine konkrete (manuelle) Konfiguration fuer den Dienst web server.
services.nginx.virtualHosts."${config.networking.fqdn}" = { services.nginx.virtualHosts."${config.networking.fqdn}" = {
#### https://search.nixos.org/options?show=services.nginx.virtualHosts.<name>.default #### https://search.nixos.org/options?show=services.nginx.virtualHosts.<name>.default
listen = [
{
port = 80;
addr = "0.0.0.0";
}
{
port = 443;
addr = "0.0.0.0";
ssl = true;
proxyProtocol = true;
}
];
default = true; default = true;
locations."/" = { locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.redmine.port}"; proxyPass = "http://127.0.0.1:${toString config.services.redmine.port}";

View file

@ -38,44 +38,15 @@
"9.9.9.9" "9.9.9.9"
"1.1.1.1" "1.1.1.1"
]; ];
firewall.enable = false; firewall = {
allowedTCPPorts = [
22
80
443
];
};
nftables = { nftables = {
enable = true; enable = true;
ruleset = ''
table inet filter {
set blacklist4 {
type ipv4_addr
flags interval
# manage at runtime: nft add element inet filter blacklist4 { 1.2.3.0/24 }
}
set blacklist6 {
type ipv6_addr
flags interval
# manage at runtime: nft add element inet filter blacklist6 { 2001:db8::/32 }
}
chain input {
type filter hook input priority filter; policy drop;
iif "lo" accept
ct state established,related accept
ip saddr @blacklist4 drop
ip6 saddr @blacklist6 drop
tcp dport { 22, 80, 443 } accept
}
chain forward {
type filter hook forward priority filter; policy drop;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
'';
}; };
}; };
@ -125,50 +96,12 @@
server proxy 141.56.51.1:80 server proxy 141.56.51.1:80
backend http_443 backend http_443
mode tcp mode tcp
server proxy 141.56.51.1:443 send-proxy-v2 server proxy 141.56.51.1:443
''; '';
}; };
}; };
users.users.root.packages = [ environment.systemPackages = with pkgs; [
(pkgs.writeShellScriptBin "nft-blacklist" ''
set -euo pipefail
usage() {
echo "Usage: nft-blacklist <add|del> <ip-or-cidr>"
echo " add - add entry to blacklist set"
echo " del - remove entry from blacklist set"
exit 1
}
[[ $# -ne 2 ]] && usage
ACTION="$1"
ADDR="$2"
if [[ "$ADDR" == *:* ]]; then
SET="blacklist6"
elif [[ "$ADDR" == *.* ]]; then
SET="blacklist4"
else
echo "Error: cannot determine address family for '$ADDR'" >&2
exit 1
fi
case "$ACTION" in
add)
${pkgs.nftables}/bin/nft add element inet filter "$SET" "{ $ADDR }"
echo "Added $ADDR to $SET"
;;
del)
${pkgs.nftables}/bin/nft delete element inet filter "$SET" "{ $ADDR }"
echo "Removed $ADDR from $SET"
;;
*)
usage
;;
esac
'')
]; ];
system.stateVersion = "25.11"; system.stateVersion = "25.11";

View file

@ -99,17 +99,6 @@
services.mediawiki.database.passwordFile = "/var/lib/mediawiki/mediawiki-dbpassword"; services.mediawiki.database.passwordFile = "/var/lib/mediawiki/mediawiki-dbpassword";
services.httpd = {
extraModules = [ "remoteip" ];
extraConfig = ''
# Trust HAProxy's address (adjust to your HAProxy IP/subnet)
RemoteIPProxyProtocol On
# RemoteIPProxyProtocolExceptions 127.0.0.1 ::1
RemoteIPTrustedProxy 141.56.51.1/32
'';
};
#### 2024-02-17 vater: #### 2024-02-17 vater:
#### trace: warning: The option `services.mediawiki.virtualHost' defined in `/etc/nixos/configuration.nix' has been renamed to `services.mediawiki.httpd.virtualHost'. #### trace: warning: The option `services.mediawiki.virtualHost' defined in `/etc/nixos/configuration.nix' has been renamed to `services.mediawiki.httpd.virtualHost'.
# services.mediawiki.virtualHost.hostName = "wiki.stura.htw-dresden.de"; # services.mediawiki.virtualHost.hostName = "wiki.stura.htw-dresden.de";
@ -161,8 +150,8 @@
Lockdown = pkgs.fetchzip { Lockdown = pkgs.fetchzip {
# url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_43-7ac8966.tar.gz"; # url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_43-7ac8966.tar.gz";
# url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_44-af1f4df.tar.gz"; # url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_44-af1f4df.tar.gz";
url = "https://extdist.wmflabs.org/dist/extensions/CategoryLockdown-REL1_45-a715472.tar.gz"; url = "https://extdist.wmflabs.org/dist/extensions/Lockdown-REL1_45-a46dbea.tar.gz";
sha256 = "sha256-1gl5m9xkmLrdjoR0M13gcQHLtZt4Bt0PUXDiDEqjpvk="; sha256 = "sha256-zTTpbQiqudLILPSzmKGjKr6wZjh0YUttGmqwjPpAToc=";
}; };
#### Hinzufuegen der Erweiterung ConfirmEdit fuer eine zusaetzliche Bestaetigung bei Bearbeitungen, etwa um Herausforderungen (aka CAPTCHA) zu stellen #### Hinzufuegen der Erweiterung ConfirmEdit fuer eine zusaetzliche Bestaetigung bei Bearbeitungen, etwa um Herausforderungen (aka CAPTCHA) zu stellen
@ -179,8 +168,8 @@
#### Hinzufuegen der Erweiterung ContributionScores fuer eine Statistik von Beitraegen nach Beitragenden #### Hinzufuegen der Erweiterung ContributionScores fuer eine Statistik von Beitraegen nach Beitragenden
#### https://www.mediawiki.org/wiki/Extension:ContributionScores #### https://www.mediawiki.org/wiki/Extension:ContributionScores
ContributionScores = pkgs.fetchzip { ContributionScores = pkgs.fetchzip {
url = "https://extdist.wmflabs.org/dist/extensions/ContributionCredits-REL1_45-22c28de.tar.gz"; url = "https://extdist.wmflabs.org/dist/extensions/ContributionScores-REL1_45-cd4c94b.tar.gz";
sha256 = "sha256-9T67jCEYQyU7P9sN7tYbnevU5+FX6Y1nydXGEdzQS9k="; sha256 = "sha256-8ClNtEQ66deKM1DsRYaaZ3KlRl4yCt6UhpXcozRQzQ8=";
}; };
#### Hinzufuegen der Erweiterung Interwiki fuer das Verwenden von Verweisen als eine Art Namensraum, wie beispielweise auf Wikipedia oder selbst festgelegte Verweise #### Hinzufuegen der Erweiterung Interwiki fuer das Verwenden von Verweisen als eine Art Namensraum, wie beispielweise auf Wikipedia oder selbst festgelegte Verweise
@ -201,8 +190,8 @@
#### https://www.mediawiki.org/wiki/Extension:UserMerge #### https://www.mediawiki.org/wiki/Extension:UserMerge
UserMerge = pkgs.fetchzip { UserMerge = pkgs.fetchzip {
# url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz"; # url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_43-ed4a689.tar.gz";
url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-433f6c2.tar.gz"; url = "https://extdist.wmflabs.org/dist/extensions/UserMerge-REL1_45-446566b.tar.gz";
sha256 = "sha256-JyY4pJNBKQ9bOKrilPWCheZ5ihWwPM6ZJ0qHsZ3coPk="; sha256 = "sha256-DTDKlzet3lThh/sRLucyb8b9lhK5FYZ+dMgwrThFFBM=";
}; };
}; };

View file

@ -1,123 +0,0 @@
{ pkgs, lib, config, ... }:
let
cfg = config.stura.monitoring;
in {
options.stura.monitoring = {
extraLogFiles = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Additional log file paths for vector to scrape and forward to Loki.";
example = [ "/var/log/nginx/access.log" "/var/log/nginx/error.log" ];
};
extraGroups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Supplementary groups added to the vector systemd service to allow reading protected log files.";
example = [ "nginx" "postfix" ];
};
extraMetricInputs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Additional vector component IDs to feed into the mimir sink alongside host_metrics.";
example = [ "proxmox_normalize_metrics" ];
};
extraLogInputs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [];
description = "Additional vector component IDs to feed into the loki sink alongside journald_logs.";
example = [ "proxmox_normalize_logs" ];
};
};
config = {
networking.hosts = {
# rewrite these host entries on each system, this does not go through proxy
"141.56.51.20" = [
"mon.adm.htw.stura-dresden.de"
"log.adm.htw.stura-dresden.de"
"met.adm.htw.stura-dresden.de"
];
};
services.vector = {
enable = true;
settings = {
sources = {
host_metrics = {
type = "host_metrics";
collectors = [
"cpu"
"disk"
"filesystem"
"load"
"host"
"memory"
"network"
"process"
];
};
journald_logs = {
type = "journald";
include_units = []; # empty = collect all units
};
} // lib.optionalAttrs (cfg.extraLogFiles != [] || config.services.nginx.enable) {
extra_log_files = {
type = "file";
include = lib.optional config.services.nginx.enable "/var/log/nginx/access.log"
++ cfg.extraLogFiles;
};
};
transforms = {
add_host_label_metrics = {
type = "remap";
inputs = [ "host_metrics" ];
source = ''
.tags.host = get_hostname!()
del(.tags.command)
'';
};
add_host_label_logs = {
type = "remap";
inputs = [ "journald_logs" ] ++ lib.optional (cfg.extraLogFiles != [] || config.services.nginx.enable) "extra_log_files";
source = ''
.host = get_hostname!()
.unit = string(."_SYSTEMD_UNIT") ?? "file"
'';
};
};
sinks = {
mimir = {
type = "prometheus_remote_write";
inputs = [ "add_host_label_metrics" ] ++ cfg.extraMetricInputs;
endpoint = "https://met.adm.htw.stura-dresden.de/api/v1/push";
tls.verify_certificate = false;
healthcheck.enabled = false;
};
loki = {
type = "loki";
inputs = [ "add_host_label_logs" ] ++ cfg.extraLogInputs;
endpoint = "https://log.adm.htw.stura-dresden.de";
labels = {
host = "{{ host }}";
unit = "{{ unit }}";
};
tls.verify_certificate = false;
encoding.codec = "json";
};
};
};
};
systemd.services.vector.serviceConfig.SupplementaryGroups =
[ "systemd-journal" ]
++ lib.optional config.services.nginx.enable "nginx"
++ cfg.extraGroups;
};
}